Есть ли способ использовать shell_exec, не дожидаясь завершения команды?
У меня интенсивная задача, которую я бы хотел выполнить в фоновом режиме.
Пользователь нажимает на страницу, запускается PHP-скрипт и, наконец, в зависимости от некоторых условий, если требуется, он должен запустить скрипт оболочки, например:
shell_exec('php measurePerformance.php 47 844 email@yahoo.com');
В настоящее время я использую shell_exec, но для этого требуется скрипт для ожидания вывода. Есть ли способ выполнить команду, которую я хочу, не дожидаясь ее завершения?
9 ответов
Как насчет добавления.
"> /dev/null 2>/dev/null &"
shell_exec('php measurePerformance.php 47 844 email@yahoo.com > /dev/null 2>/dev/null &');
Обратите внимание, что это также избавляет от stdio и stderr.
Это выполнит команду и отключится от запущенного процесса. Конечно, это может быть любая команда, которую вы хотите. Но для теста вы можете создать php-файл с помощью команды sleep(20).
exec("nohup /usr/bin/php -f sleep.php > /dev/null 2>&1 &");
Вы также можете мгновенно вернуть свой вывод клиенту и продолжить обработку PHP-кода.
Это метод, который я использую для Ajax-вызовов с долгим ожиданием, которые не будут иметь никакого эффекта на стороне клиента:
ob_end_clean();
ignore_user_abort();
ob_start();
header("Connection: close");
echo json_encode($out);
header("Content-Length: " . ob_get_length());
ob_end_flush();
flush();
// execute your command here. client will not wait for response, it already has one above.
Вы можете найти подробное объяснение здесь: http://oytun.co/response-now-process-later
В Windows 2003, чтобы вызвать другой скрипт без ожидания, я использовал это:
$commandString = "start /b c:\\php\\php.EXE C:\\Inetpub\\wwwroot\\mysite.com\\phpforktest.php --passmsg=$testmsg";
pclose(popen($commandString, 'r'));
Это работает только ПОСЛЕ предоставления изменений разрешений на cmd.exe
- добавить чтение и выполнение для IUSR_YOURMACHINE
(Я также установил запись в Deny).
Конечно, для windows
ты можешь использовать:
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("C:/path/to/php-win.exe -f C:/path/to/script.php", 0, false);
Замечания:
Если вы получите COM
ошибка, добавьте расширение к вашему php.ini
и перезапустить apache
:
[COM_DOT_NET]
extension=php_com_dotnet.dll
Используйте PHP popen
команда, например:
pclose(popen("start c:\wamp\bin\php.exe c:\wamp\www\script.php","r"));
Это создаст дочерний процесс, и сценарий будет выполнять в фоновом режиме, не ожидая вывода.
Если это не веб-страница, я рекомендую генерировать какой-то сигнал (возможно, удалив файл в каталог) и поручить заданию cron выполнить работу, которую необходимо выполнить. В противном случае мы можем попасть на территорию использования pcntl_fork()
а также exec()
изнутри процесса Apache, и это просто плохое моджо.
Это будет работать, но вы должны быть осторожны, чтобы не перегружать ваш сервер, потому что он будет создавать новый процесс каждый раз, когда вы вызываете эту функцию, которая будет работать в фоновом режиме. Если одновременно выполняется только один одновременный вызов, то этот обходной путь сделает работу.
Если нет, то я бы посоветовал запустить очередь сообщений, например, beanstalkd/gearman/amazon sqs.
Вы всегда можете публиковать поверх AJAX страницу, которая вызывает shell_exec().