场景:
这样做的最佳方式是什么?
答案 0 :(得分:11)
On * nix:
exec('/path/to/executable > /dev/null 2>&1 &');
在Windows上:
$WshShell = new COM('WScript.Shell');
$oExec = $WshShell->Run('C:\path\to\executable.exe', 0, false);
这两个都会产生一个新进程,它将同步运行,与父进程完全断开连接。只要您的主持人允许您这样做。
答案 1 :(得分:2)
你可以按键google:关闭连接后继续处理php。
以下与您的问题相关的链接是:
您可以使用belongs命令继续执行而无需用户中止
ignore_user_abort(true);
set_time_limit(0);
使用fastcgi_finish_request提醒客户端停止响应输出。并且您的脚本将继续执行。
一个例子:
// redirecting...
ignore_user_abort(true);
set_time_limit(0);
header("Location: ".$redirectUrl, true);
header("Connection: close", true);
header("Content-Length: 0", true);
ob_end_flush();
flush();
fastcgi_finish_request(); // important when using php-fpm!
sleep (5); // User won't feel this sleep because he'll already be away
// do some work after user has been redirected
答案 2 :(得分:2)
补充@DaveRandom的答案:实际上,您不需要将STDERR
重定向到STDOUT
(使用2>&1
)。
但是,如果要防止父进程挂起等待子进程完成,则需要重定向STDOUT
。这是必需的,因为exec
将返回子进程输出的最后一行,因此,它需要等待子进程STDOUT
关闭。
这并不意味着您需要将其重定向到/dev/null
。您可以将其重定向到其他文件,甚至重定向到其他文件描述符(例如STDERR
:1>&2
)。
exec('/path/to/executable')
:将启动一个新进程并等待其完成(即阻止父进程)。exec('/path/to/executable &')
:与上述基本相同。$pid = exec('/path/to/executable > /dev/null & echo $!')
:将在后台启动一个进程,子进程和父进程并行运行。 /path/to/executable
的输出将被丢弃,$pid
将接收子进程的PID。实际上没有必要使用2>&1
,因为exec
会忽略子进程的STDERR
。这也可能是不希望有的原因,因为它将使查找某些错误变得更加困难,因为它们只会被静默丢弃。如果省略2>&1
,则可以将父进程的STDERR
用管道传输到某个日志文件,稍后在出现问题时可以进行检查:
php /path/to/script.php 2>> /var/log/script_error.log
通过使用上面的代码来启动触发子进程的脚本,将script.php
和任何子进程写入STDERR
的所有内容都写入日志文件。
答案 3 :(得分:1)
PHP中没有线程。您可以通过发回一个触发Ajax调用的HTML页面来作弊,以便在新请求中启动繁重的进程。但如果它是共享主机,我的猜测是你很快就会达到托管服务提供商对内存,时间或CPU使用量的限制。
答案 4 :(得分:0)
$WshShell = new COM('WScript.Shell');
$oExec = $WshShell->Run('C:\xampp\php\php.exe C:\xampp\htdocs\test.php -a asdf', 0, true);
无法将argv传递给test.php。
var_dump($argv);