Has a handy howto to demonize a bash script.
Copied here for reference. Not my work, work of agriffis
daemonizing bashApril 20th, 2010 by agriffis
- Call fork (to guarantee the child is not a process group leader, necessary for setsid) and have the parent exit (to allow control to return to the shell). Forking in bash is a simple matter of putting a command in the background using "&". To put a sequence of commands in the background, use a subshell: "( commands ) &". Note that bash doesn't provide any method for the child process to continue the same execution path as the parent, so the entirety of the child must be contained in the subshell. The easiest way to do this is implement the child as a bash function: "childfunc &".
- Call setsid to create a new session so the child has no controlling terminal. This simultaneously prevents the child from gaining access to the controlling terminal (using /dev/tty) and protects the child from signals originating from the controlling terminal (HUP and INT, for example). Bash provides no method to call the setsid syscall for the current process. We have two less-than-ideal alternatives:
- The util-linux-ng package provides an external setsid command but this daemonizes an external command rather than the currently running script. It also makes collecting the PID of the child tricky because the setsid command will fork internally. Having said all that, if your application allows you to use the setsid command, it's a good choice because bash can't otherwise fully protect against the child process opening /dev/tty. It's still a good idea to redirect std* to prevent stray output to the terminal.
- Lacking the setsid syscall, there are steps we can take to partially protect the child process from the effects of the controlling terminal:
- Redirect std* to files or /dev/null
- Guard against HUP and INT by signal handler in child
- Guard against HUP by disown -h in parent
- Change working directory to / to prevent the daemon from holding a mounted filesystem open. Bash is good at this.
- Set umask to 0 to clear file mode creation mask. I have to admit that I can't understand the point of this, in bash or any other language. It seems to me that the child will either set its umask explicitly before creating files, or it will set individual file permissions explicitly, or it will fall back on the caller's umask. In the last case, I want my inherited umask, not the wide-open zero. If anybody wants to explain a good reason for step 4, I'm all ears... Until then, it's commented out in my implementation below.
- Close unneeded file descriptors. This step is fun in bash using eval and brace expansion...
functions here, "daemonize" for an external command using setsid,
"daemonize-job" for a function in the running script.