Возможно вычеркнуть процесс из PHP-скрипта, который обрабатывает запрос веб-сервера, но вам следует остерегаться нескольких вещей:
- Ваш оригинальный процесс PHP и разветвленный процесс будутвероятно, разделяют много объектов данных.Хотя некоторые переменные могут быть скопированы и могут обрабатываться независимо в дочернем и родительском процессах, некоторые переменные (например, соединения db или файловые дескрипторы и т. Д.) Могут ссылаться на один и тот же вычислительный ресурс.Вы должны быть осторожны, чтобы избежать повторного использования переменных ресурса.Попросите ребенка повторно подключиться к вашей БД и заново открыть файлы и т. Д.
- Если процесс отключается, у него могут возникнуть проблемы с подключением к БД или почтовому шлюзу и т. Д. Вероятно, вы должны сделать этот разветвленный дочерний цикл процесса следующимпопытайтесь достичь своей цели и затем в конечном итоге умрете после определенного числа попыток, если он делает что-то важное.
- Вероятно, есть еще дюжина других предупреждений о многопоточности, условиях гонки, использовании ресурсов и т. д. Просто помните, что отключениепроцессы означают, что вы потребляете больше ресурсов, что эти ресурсы могут использоваться другими процессами, и у вас могут возникнуть странные, трудно устраняемые проблемы.
Все это говорит, у меня были некоторыеудачи, используя комбинацию команды exec для отключения отдельного процесса, а затем вызывая функцию posix_setsid , чтобы разветвленный дочерний процесс мог полностью отсоединиться от apache и продолжить работу дажеесли родительский процесс завершается или apache перезапускается или whatever.
ИСПОЛЬЗУЙТЕ ЭТОТ КОД НА СВОЙ СТРАХ И РИСК.
С помощью скрипта CodeIgniter вы можете отключить дочерний процесс с помощью exec, например:
// the PARENT process (a CodeIgniter script running in response to http request)
// put this code in a controller or something
// here's a command to run the PHP executable in the background on some file
// routing the output and error messages to another file
$cmd = "/usr/bin/php /path/to/child-script.php > /tmp/foo/out.txt 2>&1 & echo \$!";
// will contain an array of output lines from the exec command
$cmd_output = NULL;
// will contain the success/failure code returned by the OS.
// Will be zero for a valid command, non-zero otherwise
$cmd_result = NULL;
// $return will contain the last line from the result of
// the command which should be the PID of the process we have spawned
$cmd_return = exec ( $cmd, $cmd_output, $cmd_result );
ПРИМЕЧАНИЕ: вместо этого вы можете использовать pcntl_fork , чтобы отключить процесс.Причина, по которой я этого не сделал, заключается в том, что это означает, что дочерний процесс наследовал бы каждую переменную в родительском скрипте codeigniter , что может привести к некоторому непонятному поведению.Например, если один процесс изменяет соединение с БД, это изменение может внезапно появиться в другом сценарии и т. Д. Использование exec () здесь более тщательно разделяет два сценария и делает вещи проще.Если вы хотите изменить $ cmd выше для запуска контроллера CodeIgniter, см. CodeIgniter из командной строки .
В дочернем процессе вы должны вызвать posix_setsid (), чтобы дочерний скрипт отключалсясам от родителя.Если вы этого не сделаете, то дочерний процесс может быть уничтожен, когда родительский процесс завершится (или будет уничтожен), или если веб-сервер перезапустится или выйдет из строя или что-то в этом роде.
Вот код в дочернем процессе, который требуетрасширение POSIX, которое должно быть установлено, включено и не отключено в PHP.ini с помощью директивы disable_functions .Это расширение очень часто отключается (и по уважительной причине) в PHP.ini вашего веб-сервера, но иногда все еще доступно для сценариев CLI.Еще одна веская причина использовать exec для отключения процесса командной строки.
// child-script.php
// CHILD process. Put your emailing code or other long-running junk in here
// because this is a brand-new, separate process, you might need to load configuration files, connect to the db, etc.
if (!extension_loaded("posix")){
throw new Exception("This script requires posix extension");
}
// NOTE: the output and results of this file will be completely unavailable to the parent script and you might never know what happens if you don't write a log file or something. Consider opening a log file somewhere
// process id of this process, should match contents of $cmd_return above
$mypid = posix_getpid();
// session id -- not to be confused with php session id
// apparently this call will make this process a 'session leader'
$sid = posix_setsid();
if ($sid < 0) {
throw new Exception("setsid failed, returned $sid");
}
// this output should be routed by the exec command above to
// /tmp/foo/out.txt
echo "setsid success, sid=$sid\n";
// PUT YOUR EMAILING CODE HERE