有没有办法在不等待命令完成的情况下使用 shell_exec ?

Posted

技术标签:

【中文标题】有没有办法在不等待命令完成的情况下使用 shell_exec ?【英文标题】:Is there a way to use shell_exec without waiting for the command to complete? 【发布时间】:2010-11-04 10:15:30 【问题描述】:

我有一个需要在后台运行的进程密集型任务。

用户点击一个页面,php脚本运行,最后,根据一些条件,如果需要,它必须运行一个shell脚本,例如:

shell_exec('php measurePerformance.php 47 844 email@yahoo.com');

目前我使用shell_exec,但是这需要脚本等待输出。有什么方法可以执行我想要的命令而不等待它完成?

【问题讨论】:

注意:该进程必须立即启动,因此不能选择 cron。 请注意:确保页面不会被所有人(搜索引擎/欺诈用户)访问,如果您在共享环境中,所有脚本的执行时间(特别是 php !)可能是有限的。无论如何,您可能想看看 set_time_limit/php.ini。 php execute a background process的可能重复 【参考方案1】:

添加怎么样。

"> /dev/null 2>/dev/null &"

shell_exec('php measurePerformance.php 47 844 email@yahoo.com > /dev/null 2>/dev/null &');

请注意,这也摆脱了 stdio 和 stderr。

【讨论】:

没有。没有副作用。如果您有时决定想要进程的 stdio 或 stderr 输出,请考虑 ***.com/questions/45953/… 问题:这只是丢弃输出,对吗? PHP 在继续执行之前是否仍然等待进程完成,还是会触发并忘记? 是丢弃。是的,一发不可收拾 注意:在其他答案中看到的> /dev/null 2>&1 & 是此处给出的> /dev/null 2>/dev/null & 的简洁形式。这基本上是说“将 STDERR (2) 重定向到与 STDOUT (&1) 相同的位置”。 我通常通过添加 echo $! 来获取运行脚本的 PID! >> /tmp/pid.txt 在 exec 命令的末尾,但是通过将输出和错误重定向到 /dev/null,没有更多的 pid 文件:你们中的任何人都可以在不等待输出的情况下获得 exec 启动的脚本的 PID 吗? 【参考方案2】:

这将执行一个命令并与正在运行的进程断开连接。当然,它可以是您想要的任何命令。但是对于测试,您可以使用 sleep(20) 命令创建一个 php 文件。

exec("nohup /usr/bin/php -f sleep.php > /dev/null 2>&1 &");

【讨论】:

这个好还是shell_exec好? 嗨,我可以使用这个 shell_exec("nohup /usr/bin/php -f example.com/notifications/sendnotifications_async > /dev/null 2>&1 &"); 为什么both nohup&?【参考方案3】:

您还可以立即将输出返回给客户端,然后继续处理您的 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

【讨论】:

Ops...我在这里唤醒了一个僵尸问题,我还没有意识到。但这一点信息可能对其他人有益。 这与 shell_exec 没有任何关系 我正在使用它进行本地到远程测试。在远程本身上,我使用 shell_exec。谢谢 :)【参考方案4】:

在 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 添加读取和执行(我还将写入设置为拒绝)。

【讨论】:

【参考方案5】:

使用 PHP 的popen 命令,例如:

pclose(popen("start c:\wamp\bin\php.exe c:\wamp\www\script.php","r"));

这将创建一个子进程,脚本将在后台执行,无需等待输出。

【讨论】:

等待子进程结束。至少赢了 这里的后台是在Windows“start”命令的帮助下实现的另一个操作系统...但它确实对我有用,谢谢! :-) 这在 win 10 上对我有用,但不会弹出 cli 窗口:start /B php wait.php args【参考方案6】:

当然,对于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

【讨论】:

我不知道,但它对我有用。请任何人解释 wscript.shell 是什么以及它的作用。 你能解释一下为什么这条线没有给出任何输出吗? ` $oExec = $WshShell->Run('C:\Users\Shreyash\Desktop\phantomjs-2.1.1-windows\bin\phantomjs.exe -f C:\xampp\htdocs\composer\test_0.js', 0 , 假);` test_0.js 可能有错误,检查幻像日志。【参考方案7】:

如果它不在网页上,我建议生成某种信号(也许将文件放入目录中)并让 cron 作业接手需要完成的工作。否则,我们很可能会从 Apache 进程内部进入使用 pcntl_fork()exec() 的领域,这很糟糕。

【讨论】:

你说这是一种糟糕的魔力。你能详细说明一下吗?【参考方案8】:

这可行,但您必须小心不要使服务器过载,因为每次调用此函数时它都会创建一个新进程,该进程将在后台运行。如果同时只有一个并发调用,那么这个解决方法就可以了。

如果没有,那么我建议运行一个消息队列,例如 beanstalkd/gearman/amazon sqs。

【讨论】:

以上是关于有没有办法在不等待命令完成的情况下使用 shell_exec ?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用 time.Sleep 的情况下等待所有 goroutines 完成?

在不出现 Windows 控制台的情况下运行 Python 脚本

如何在不关闭 Executor 的情况下等待 ThreadPoolExecutor 中的所有任务完成?

如何在不使用“sh”或“bash”命令的情况下运行 shell 脚本?

如何在不等待完成的情况下调用存储过程?

有没有办法在不使用画布 API 的情况下从图像文件中获取二进制数据?