dongruolin5324 2015-06-13 12:29
浏览 541
已采纳

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

I am currently building a Laravel app that should start external processes and then monitor their status using the process ID.

The processes are started like this, returning the pid:

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

This works fine. But now I have problems tracking the status of the newly started process, presumably because the methods I use require the checked process to be a child process of the shell executing the commands.

Currently I try to determine if the process is still running by:

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

This retruns true if the process is still running but works only with child processes. I should be able to use kill -0 <pid> here instead, so this is not a big problem.

What is the problem, though, is determining the exit code of the process. My current code looks like this:

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

When the process is finished, wait should immediately return and write the exit code to $?. But this also works only for child processes of the shell that executed the original command, so I always get the exit code 127 (is not a child of this shell).

Is there any other way of getting the exit code of a process?

Also, I use the same Laravel queue both for starting and monitoring the processes (with the php artisan queue:listen command) so the exec() methods are called from within the same process. Or does PHP start a separare shell for each exec() call?

Edit: I know now that Laravel does start a new process for every queued command so starting the scripts and monitoring their state is done in different processes.

  • 写回答

2条回答 默认 最新

  • dongxianghuan3587 2015-06-15 14:26
    关注

    I've now worked around this issue by writing the exit code to a log file once the long running script is finished. By adding this to the initial command, I can "fire and forget" the process and check the status code from the log file later.

    This is the command (wasn't really easy to come by):

    $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 $!');
    

    Monitoring the running process works well using the kill -0 method with the process ID:

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

    This requires the PHP/Apache user to be able to send a kill signal to the process but this requirement should be met because the process was launched by the same user that now tries to monitor it.

    Once the process is no longer running, I can determine if it was successful by checking the log file.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 划分vlan后不通了
  • ¥15 GDI处理通道视频时总是带有白色锯齿
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序
  • ¥100 角动量包络面如何用MATLAB绘制
  • ¥15 merge函数占用内存过大
  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大