简体   繁体   中英

Start and monitor process with 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.

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.

The exec() function actually accepts additional arguments for capturing both the process output and the exit code of the process.

example:

exec('nohup <script>', $output, $code); var_dump($code);

should output: int(0) or whatever status code is expected.

see http://us2.php.net/manual/en/function.exec.php for more.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM