什么可能会不合需要地停止长期运行的PHP脚本?

If a long running php script is created in a LAMP stack, using:

set_time_limit(0);
header("Connection: close");
ignore_user_abort(true); // just to be safe
ob_start();

$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();            
session_write_close();

//Some long running code here

In what ways could this script subsequently be terminated externally (to the script itself)?

The major reasons why your example script would end unexpectedly or undesireably are:

  • reboot and shutdown - this should be ovious.

  • memory limits of PHP, of Apache, or running out of memory on OS level will kill this script.

  • in some setups, there might be limits for used CPU cycles, too.

  • any PHP fatal error that occurs during runtime.

  • kill <pid> with almost any signal (not only kill -9) will terminate the script.

  • If the script is running inside apache using mod_php, then apache restarts would also kill the script.
    Note that each long running script inside apache blocks a worker thread/process, which might be bad for your server performance. This may not apply in a php-fcgi environment!

To prevent some of this:

  • Run the script outside the apache environment.
    I prefer calling echo '/usr/bin/php myscript.php'| at now. (using at scheduler, see manpage)

    at totally detaches your script from apache, so it will still run when the apache process ends.

  • set the PHP memory limit to a high value or infinite. (anything > 512M is generally a bad idea)
    This can be done inside the script.

You can create a bash script, that are running for too long and execute it using a cronjob.

For example:

#!/bin/bash
# This script will kill process which running more than X hours
# egrep: the selected process; grep: hours
PIDS="`ps eaxo bsdtime,pid,comm | egrep "spamd|exim|mysqld|httpd" | grep " 1:" | awk '{print $2}'`"

# Kill the process
echo "Killing spamd, exim, mysqld and httpd processes running more than one hour..."
for i in ${PIDS}; do { echo "Killing $i"; kill -9 $i; }; done;

http://forum.directadmin.com/showthread.php?t=26179