php - 使用 exec() 启动和监视进程

标签 php shell laravel

我目前正在构建一个 Laravel 应用程序,该应用程序应该启动外部进程,然后使用进程 ID 监视其状态。

进程像这样启动,返回pid:

exec('nohup <script> & echo $!');

这很好用。但现在我在跟踪新启动进程的状态时遇到问题,大概是因为我使用的方法要求检查的进程是执行命令的 shell 的子进程。

目前我尝试通过以下方式确定进程是否仍在运行:

exec("ps -p $pid -o pid=") == $pid;

此重播true如果进程仍在运行但仅适用于子进程。我应该能够使用kill -0 <pid>在这里,所以这不是一个大问题。

问题是什么,但是,确定进程的退出代码。我当前的代码如下所示:

exec("wait $pid; echo \$?");

该过程完成后,wait应立即返回并将退出代码写入 $? 。但这仅适用于执行原始命令的shell的子进程,因此我总是得到退出代码127 (不是此 shell 的子级)。

还有其他方法可以获取进程的退出代码吗?

此外,我使用相同的 Laravel 队列来启动和监视进程(使用 php artisan queue:listen 命令),因此 exec()方法从同一进程内调用。或者 PHP 是否为每个 exec() 启动一个单独的 shell打电话?

编辑:我现在知道 Laravel 确实为每个排队命令启动一个新进程,因此启动脚本并监视其状态是在不同的进程中完成的。

最佳答案

我现在已经解决了这个问题,方法是在长时间运行的脚本完成后将退出代码写入日志文件。通过将其添加到初始命令中,我可以“触发并忘记”该进程,并稍后从日志文件中检查状态代码。

这是命令(并不容易获得):

$pid = exec('('.
   // don't listen to the hangup signal
   // invoke the script and write the output to the log file
   "nohup $script >> $logFile 2>&1; ".
   // when the script is finished, write the exit code to the log file
   'echo "Exit code $?" >> '.$logFile.
   // discard the output of the `()' part so exec() doesn't
   // wait for the process to be finished,
   // then send the `()' part to the background
   ') > /dev/null 2>&1 & '.
   // immediately return the process id of the background process
   'echo $!');

使用带有进程 ID 的 kill -0 方法可以很好地监视正在运行的进程:

// true if the process is still running
exec("kill -s 0 $pid 1>/dev/null 2>&1; echo $?") === '0'

这要求 PHP/Apache 用户能够向进程发送终止信号,但应该满足此要求,因为该进程是由现在尝试监视它的同一用户启动的。

一旦进程不再运行,我可以通过检查日志文件来确定它是否成功。

关于php - 使用 exec() 启动和监视进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30818686/

相关文章:

php - Laravel 5.3 中的搜索栏以过滤表格

Laravel Eloquent 分页关系未显示在集合中

从 Laravel 的belongsToMany 关系中选择自定义列

php - 加拿大邮政 'lookup postal code' 屏幕抓取代码

php - 将自动增量值插入另一列

linux - 将 shell 脚本结果输出到文件,如终端屏幕

shell - awk 捕捉文本进入下一行

Linux 脚本变量无法正确识别

php - 从mysql读取秒并转换为小时

php - 使用 PHP 查看 S3 中是否存在对象