For several scripts run by cron on a linux/mysql system, I'd like to log all stdout and stderr output to a file. I'm currently using this code to manually write to a log file:

$scriptName = "checkStores"; # For checkStores.php
$logPath = "/usr/local/company/bin/logs/";
$logPathAndFile = $logPath . $scriptName . ".log";
$logStart = "\n\n----" . date("Y-m-d H:i:s") . "----\nLog entry for " . $scriptName . ".php\n";
if (!$log = fopen($logPathAndFile,"a")) { echo "Cannot open log file [$logFile]\n"; }

if (!fwrite($log, $logStart)) { echo "Cannot write to log file [$logFile]\n"; }

This works, but all log entries are manual and stderr output goes to the system log. Is there a way to redirect all stdout and stderr to a log file?

Here's perl code I've recently used to log everything (stdout and stderr) to a file. An equivalent function in php is what I'm trying to build.

sub createLog
{
my $logFile = shift;
open ( STDERR, ">>$logFile" );
open ( STDOUT, ">>$logFile" );
open LOG, ">>$logFile" || die "$0: Can't open log file!";
select( LOG );
$| = 1; # Turn on buffer autoflush for log output
print "$0: Starting script ...\n";
select( STDOUT );
}

I know that one can redirect I/O from the shell, but I'd prefer to so do this within each php script.

    You can output to stdout with a simple echo ..

    Output to stderr is a little more tricky..

    if ($fp = fopen('php://stderr', 'a')) {
      fwrite($fp, 'output to stderr');
      fclose($fp);
    }
    

    now.. if you want to redirect both outputs there is a way from shell. Say your file is myfile.php and the output file is output.txt

    php -f myfile.php &>output.txt

      It's looking you just can't do this in PHP without some extensive error handling code. Odd. All I really want to do is redirect all stderr and stdout to a single log file.

        PHP does not output anything to stderr because it is supposed to be a script engine running under a web server. stdin stdout and stderr are streams for the shell.

        On the other hand.. even in C you need to use explicit calls to the stderr stream with fprintf(). Its not that dramatic to make special handling code to use the stderr stream.

        I have the feeling that there is more to it.. if you give us more info on that you 're up to we could give you more help.

          Here's my situation: I inherited about thirty scripts that run daily via cron in production, all in PHP and none do anything web related. They retrieve remote data files, parse data, and store it in databases. Some query databases and generate reports that are e-mailed to customers. Most had little or no error handling, so debugging problems related to failed scripts and dependencies is difficult.

          I've gradually been adding progress statements in the scripts that let me see how far they go before something breaks. To monitor all these scripts, I piped the output of each script to mail so I could see how things worked with something like this.

          35 06 * /<path>/import1.php | mail me@company.com -s "Daily import1.php output"

          After the scripts became stable I wanted a log to track any issues without receiving 30 e-mails each day. So, I added logging code as I posted initially to append progress statements to a log file for each script. This is similar to what I'd done in the past with perl, where progress and all stdout and stderr was logged and only serious errors triggered e-mail to IT.

          So, thats the goal: Have each script send all of its output of any kind to a log file so I can review it when possible. Long-term, a more robust system will be developed so this is easier to manage. Right now I'm too busy fighting small fires...

            I see..
            As far as I know PHP does not output to stderr unless you use the php://stderr stream. Any mistakes would normaly go to stdout. But even if it does, or if you use a non-PHP script this sounds like an administration problem, not PHP.

            I am not an expert in shell programming but here is an approach that would work for you. Put sequencial shell commands that use a common temporary file:

            35 06 * * * /<path>/import1.php &>output.txt; cat output.txt | mail me@company.com -s "Daily import1.php output"; rm -f output.txt
            

            Perhaps someone else can come up with a better solution.

              Write a Reply...