场景:
最好的方法是什么?
在*nix上:
exec('/path/to/executable > /dev/null 2>&1 &');
在 Windows 上:
$shell = new COM('WScript.Shell');
$proc = $shell->Run('C:\path\to\executable.exe', 0, false);
这两个进程都会生成一个新进程,该进程将异步运行,与父进程完全断开连接。只要你的主人允许你就可以这样做。
为了补充@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
的所有内容都将写入日志文件。
以下与您的问题相关的链接是:
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
$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);