views:

773

answers:

5

Is there a way to start a script from another process, so that if the process dies/ends, the script still continues?

Will setuid do this? If I were to set the owner to root, and then start the script?

For example, if I have some PHP code starting a script, but httpd dies or gets killed, I think that it takes my script with it. Is there a way around this?

Specifically, I'm on Fedora 10 with Apache 2 and PHP 5.

+4  A: 

From here:

function become_daemon() 
{
    $child = pcntl_fork();
    if($child) {
        exit; // kill parent
    }
    posix_setsid(); // become session leader
}

Additionally, it's a good idea to close STDIN, STDOUT, and STDERR but I'm not sure how to do that in PHP.

bmdhacks
fork() is the correct way to do this, but you should technically fork a second time so that the process isn't a session leader, and can't reacquire a controlling terminal
JimB
I think I can just close STDIN, STDOUT and STDERR in the call to my script. Or rather, redirect somewhere else.
SkippyFire
So forking essentially breaks the process off into another process right? But if there are limitations on the execution time of a process started from PHP, would those limitations still apply? My script seems to die after a week, but runs fine from the command line.
SkippyFire
it depends on what's killing it. forking correctly (twice), closing your file descriptors, and making sure you're in a safe directory are a good start though.
JimB
FYI this requires the Process Control Extensions Library to be compiled with PHP, and guess what! My build doesn't have it :( FYI, the library is here: http://www.php.net/pcntl_forkI'll just have to take your word for it now :)
SkippyFire
A: 

From the command shell you can append an ampersand (&) on the end of your command-line to launch the command in the background, which detaches it from the shell.

Some good info here: http://www.linuxforums.org/forum/linux-programming-scripting/50096-moving-processes-background-foreground.html

lennyk
SkippyFire
-1 backgrounding a process has nothing to do with detaching it from it's parent
JimB
A: 

You can use the "disown" built-in in bash to detach a job from the shell that spawned it. See: http://www.faqs.org/docs/bashman/bashref_79.html

Nathan
A: 

You should use php's pcntl_fork() (as recommended by @bmdhacks).

The basics process is, fork, setsid, fork again, chdir to /, and close all your open file descriptors. Standard practice also dictates that you create a file called /var/run/$NAME, (where $NAME is your daemon's name), and write the PID to that file, so that you can control the process execution later on.

I'm not a php programmer, but this is standard *nix stuff. The best php example I can google looks like this hello-world-daemon-with-fork But, he doesn't change his working directory to '/', nor does it look like he closed open file descriptors (I'm not sure how this would work in php), so that he's not connected to the stdin, stdout, and stderr of the original process.

I dug a little more, and found another article which may help with php's pcntl_fork()

And, it looks like there's a pear module called System_Daemon, which handles this for you (I found it through here).

JimB
+3  A: 

Try "nohup yourscript.sh &"

Aaron
[revised comment] You should make sure you explicitly redirect all your streams appropriately. While this method works, there are better, more controllable ways of doing this.
JimB
But those ways assume you have control over the child process and you want to change them. Poster did not specify. If you are kicking off wget to grab an iso image or something, nohup is a much better method than recompiling wget to daemonize. But yes, redirecting your streams is better, otherwise you end up with nohup.out files littered around.
Aaron
No, I wasn't recommending patching wget :) I guess it's not clear from the OP that he wanted to create a true daemon process. I gathered that from one of his comments where he said it's running php, and dies after a week
JimB