PHP: how to start a detached process?
11,518
Solution 1
No, detaching can't be done with exec()
directly (nor shell_exec()
or system()
, at least not without changing the command, and using third-party tool which does detach).
If you have the pcntl extension installed, it would be:
function detached_exec($cmd) {
$pid = pcntl_fork();
switch($pid) {
// fork errror
case -1 : return false;
// this code runs in child process
case 0 :
// obtain a new process group
posix_setsid();
// exec the command
exec($cmd);
break;
// return the child pid in father
default:
return $pid;
}
}
Call it like this:
$pid = detached_exec($cmd);
if($pid === FALSE) {
echo 'exec failed';
}
// ... do some work ...
// Optionally, kill child process (if no longer required).
posix_kill($pid, SIGINT);
waitpid($pid, $status);
echo 'Child exited with ' . $status;
Solution 2
Provided your current user has sufficient permissions to do so this should be possible with exec
and alike:
/*
/ Start your child (otherscript.php)
*/
function startMyScript() {
exec('nohup php otherscript.php > nohup.out & > /dev/null');
}
/*
/ Kill the script (otherscript.php)
/ NB: only kills one process at the time, otherwise simply expand to
/ loop over all complete exec() output rows
*/
function stopMyScript() {
exec('ps a | grep otherscript.php | grep -v grep', $otherProcessInfo);
$otherProcessInfo = array_filter(explode(' ', $otherProcessInfo[0]));
$otherProcessId = $otherProcessInfo[0];
exec("kill $otherProcessId");
}
// ensure child is killed when parent php script / process exits
register_shutdown_function('stopMyScript');
startMyScript();
Author by
Dalius
Updated on July 22, 2022Comments
-
Dalius over 1 year
Currently my solution is:
exec('php file.php >/dev/null 2>&1 &');
and in file.php
if (posix_getpid() != posix_getsid(getmypid())) posix_setsid();
is there any way I can do this just with exec?
-
Dalius over 10 yearsI do not want to daemonize the process nor do I need to fork it. I just need to start another php process that wouldn't receive SIGINT when the one who created it exits. (I'm not really sure how a daemon is different from a process that is detached from the terminal?)
-
hek2mgl over 10 yearsCheck my example again. Isn't it what you want? ;) The only difference to a daemon is that the does not run forever but will be killed on fathers exit.
-
Dalius over 10 yearsBasically yes, but try implementing that in a simple function that returns true or false. (It MUST NOT block). And I don't want the new process to be killed, it will exit itself.
-
Dalius over 10 yearsYes it is :) Though I think it's an overkill to make a fork, so I think I'll stick with detaching the process when it starts.
-
hek2mgl over 10 yearsWhat do you expect
exec()
does under the hood? It will start a shell (that's why you can use output redirection in commands) You may replace theexec()
in child with the actual php code of the child.. (can be a function or a class method, ....) then you'll save the additional shell and the php-cli call and it would be best for performance -
user229044 over 10 yearsPlease do not do this ever again: stackoverflow.com/review/suggested-edits/3201462 This is absolutely not how Stack Overflow works. You are way, way out of line, crossing out somebody else's answer and pointing their answer to your own.
-
Philzen over 10 yearsApologies - no pun intended. I was under the impression S.O. was very serious about not having incorrect information here, thus i merely suggested to remove hek2mgl's info that this couldn't be done with exec() function.
-
user229044 over 10 yearsVoting is the way we sort content here.
-
Philzen over 10 years@hek2mgl Looking at the example in my answer, could you look into updating/deleting the first sentence in yours? Otherwise your solution looks very clean and feasible :)
-
hek2mgl over 10 years@Philzen Yours is a working solution but it is more a shell script than a PHP script. The work of detaching the process is not done by the
exec()
function, it is done by nohup. But in was questioned whether theexec()
function can do it. However yours is a good workaround if the pcntl extension isn't installed -
hek2mgl over 10 yearsThis is a good workaround if the pcntl extension isn't available +1
-
Philzen over 10 years"detaching the process is not done by the exec() function, it is done by nohup" - fair point you have there :)
-
vvolodko over 9 yearsIf parent process won't exit immediately after fork the child process should fork one more time to prevent creating zombie.
-
hek2mgl over 9 years@vvolodko Thanks for your hint! (and srry for my late reply) Will read through this and update my answer