在 PHP 中启动新进程/线程的最简单方法

问题描述 投票:0回答:5

场景:

  1. 共享托管,因此无法安装新扩展+没有 CRON
  2. 提交的请求需要执行一些繁重的流程。
  3. 我希望尽快给客户答复,并立即继续繁重的工作,但不要阻止客户。
  4. 可以在新线程上(如果可能的话),启动新进程也没有问题。

最好的方法是什么?

php multithreading performance process
5个回答
11
投票

在*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);

这两个进程都会生成一个新进程,该进程将异步运行,与父进程完全断开连接。只要你的主人允许你就可以这样做。


4
投票

为了补充@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
投票
可以通过按键google:php关闭连接后继续处理。

以下与您的问题相关的链接是:

  • 关闭连接后继续处理
  • http://php-fpm.org/wiki/Features#fastcgi_finish_request.28.29
  • http://www.php.net/manual/en/features.connection-handling.php
您可以使用Belong命令继续执行而无需用户中止

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
    

1
投票
PHP 中没有线程。您可以通过发回 HTML 页面来进行作弊,该页面触发 Ajax 调用以在新请求中启动繁重的进程。但如果是共享托管,我的猜测是您很快就会达到托管提供商对内存、时间或 CPU 使用率的限制。


-1
投票
$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);
    
© www.soinside.com 2019 - 2024. All rights reserved.