views:

82

answers:

5

I have a long running PHP script that has a memory leak which causes it to fail part way through. The script uses a 3rd party library and I haven't been able to find the source of the leak.

What I would like to do is create a bash script that continually runs the PHP script, processing 1000 records at a time, until the script returns an exit code saying it has finished processing all records. I figure this should help me get around the memory leak because the script would run for 1000 records, exit, and then a new process would be started for another 1000 records.

I'm not that familiar with Bash. Is this possible to do? How do I get the output from the PHP script?

In pseudocode, I was thinking of something along the lines of:

do:
  code = exec('.../script.php')
   # PHP script would print 0 if all records are processed or 1 if there is more to do
while (code != 0)
+2  A: 

$? gives you the exit code of a program in bash

You can do something ilke

while /bin/true; do
  php script.php
  if [ $? != 0 ]; then
     echo "Error!";
     exit 1;
  fi
done

You can probably even do:

while php script.php; do
   echo "script returned success"
done
The second example will work fine, no need to use $? and test.
Bart Sas
You don't have to use `/bin/true`, Bash has a `true` builtin. You don't need to use `$?` either. Your second example is the correct way.
Dennis Williamson
In shell, programs must return 0 on success. Remember this for loops :)
levif
A: 

Use a simple until loop to automatically test the exit status of the PHP script.

#!/bin/sh
until script.php
do
   :
done

The colon is merely a null operator, since you don't actually want to do anything else in the loop. until while execute the command script.php until it returns zero (aka true). If the script returned 0 to indicate not done instead of 1, you could use while instead of until.

The output of the PHP script would go to standard out and standard error, so you could wrap the invocation of the shell script with some I/O re-direction to stash the output in a file. For example, if the script is called loop.sh, you'd just run:

./loop.sh > output.txt

though of course you can control the output file directly in the PHP script; you just have to remember to open the file for append.

You might want to ask a separate question about how to debug the PHP memory leak though :-)

Emil
+1  A: 

Do you have to use bash? You could probably do this with PHP:

while (true) {
  $output = exec('php otherscript.php', $out, $ret);
}

The $ret variable will contain the exit code of the script.

Robin
Good idea. I decided to go this route. See http://stackoverflow.com/questions/3763304/continually-running-php-script-using-bash/3764636#3764636 for my solution.
Matt McCormick
+1  A: 

You can write:

#!/bin/bash 

/usr/bin/php prg.php # run the script.
while [  $? != 0 ]; do # if ret val is non-zero => err occurred. So rerun.
  /usr/bin/php prg.php
done
codaddict
A: 

Implemented solution in PHP instead as:

do {
    $code = 1;
    $output = array();
    $file = realpath(dirname(__FILE__)) . "/script.php";
    exec("/usr/bin/php {$file}", $output, $code);

    $error = false;
    foreach ($output as $line) {
        if (stripos($line, 'error') !== false) {
            $error = true;
        }
        echo $line . "\n";
    }
} while ($code != 0 && !$error);
Matt McCormick