in reply to how to catch STDOUT from an external app, that never exits?

The problem is that the program (and file handles) work differently than you think :

  1. You open the log file. The OS gives you back a number. Let's call this number the 'file handle'.
  2. The external program gets run, and is handed that number.
  3. A new day breaks.
  4. Your program closes its file handle via the number.
  5. Your program opens a new file and gets a new handle.
  6. The still running application still writes to the old file handle.

Under Linux and possibly also under Windows NT and higher, you can rename the file while it is still open, depending on the open mode / locking mode (there is a savelogs script that does just that). If this does not work with the external program, you will have to stop and restart the application to rotate the logfile.

Update: Fixed link, thanks to Tomte

perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The $d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider ($c = $d->accept())->get_request(); $c->send_response( new #in the HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web

Replies are listed 'Best First'.
Re: Re: how to cath STDOUT from an external app, that never exits?
by ThorstenHirsch (Novice) on Apr 09, 2003 at 09:06 UTC
    Thank you, so far.

    But I'd prefer not to rely on the savelogs script, but use a self written method.
    Is it possible to use pipes, which don't wait for the application to terminate? I mean to open a pipe and run the application in the background. That's what I tried with open(), but it seemed for me that open() always waits for application to terminate, before it gives STDOUT and STDERR to the pipe.

    Btw: the OS is Win2000 Server.

    Bye. Thorsten

      I think that you will have to write a wrapper application that reads the executable output line by line and writes that output into a different logfile - as long as you can make the external application write everything to stdout/stderr, this should be possible. I don't have the time to create a working script, but here are some simple cases that could work (depending on the application) :

      open APP, 'application.exe |' or die "Uhoh : $!"; while (<APP>) { my $filename = get_logfilename_of_today; open LOG, "<", $filename; print LOG $_; close LOG; };

      The above part only works if the application does not write to STDERR. perldoc perlipc suggests the following snipped if you need to read and write :

      use FileHandle; use IPC::Open2; $pid = open2(*Reader, *Writer, "cat -u -n" ); print Writer "stuff\n"; $got = <Reader>;

      If you need to read and write, also take a look at IO::Select.

      perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The $d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider ($c = $d->accept())->get_request(); $c->send_response( new #in the HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web
        Thanks Corion,

        but I also tried it that way. It doesn't work, because
        open APP, 'application.exe |';
        does also wait for application.exe to finish.

        And with you second piece of code, it's the same.
        The only way to start application.exe in the background is open3 with the ">&" in the filehandlers.

        Bye.
        Thorsten