Some of the answers above do not include some important parts of what makes a daemon a demon, not just a background process, or a background process separate from the shell.
This http://www.faqs.org/faqs/unix-faq/programmer/faq/ describes what it takes to be a demon. And this Run bash script as a daemon implements setid, although it skips chdir for root.
The original question with the poster was more specific than βHow to create a daemon process using bash?β, But since the topic and answers discuss demounting shell scripts in general, I think itβs important to indicate this (for intruders, I look at the small details of creating a daemon )
Here's my execution of a shell script that will behave according to the FAQ. Set DEBUG to true to see a pretty output (but it also crashes quickly, and not cyclically):
#!/bin/bash DEBUG=false # This part is for fun, if you consider shell scripts fun- and I do. trap process_USR1 SIGUSR1 process_USR1() { echo 'Got signal USR1' echo 'Did you notice that the signal was acted upon only after the sleep was done' echo 'in the while loop? Interesting, yes? Yes.' exit 0 } # End of fun. Now on to the business end of things. print_debug() { whatiam="$1"; tty="$2" [[ "$tty" != "not a tty" ]] && { echo "" >$tty echo "$whatiam, PID $$" >$tty ps -o pid,sess,pgid -p $$ >$tty tty >$tty } } me_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" me_FILE=$(basename $0) cd / #### CHILD HERE ---------------------------------------------------------------------> if [ "$1" = "child" ] ; then # 2. We are the child. We need to fork again. shift; tty="$1"; shift $DEBUG && print_debug "*** CHILD, NEW SESSION, NEW PGID" "$tty" umask 0 $me_DIR/$me_FILE XXrefork_daemonXX "$tty" "$@" </dev/null >/dev/null 2>/dev/null & $DEBUG && [[ "$tty" != "not a tty" ]] && echo "CHILD OUT" >$tty exit 0 fi ##### ENTRY POINT HERE --------------------------------------------------------------> if [ "$1" != "XXrefork_daemonXX" ] ; then # 1. This is where the original call starts. tty=$(tty) $DEBUG && print_debug "*** PARENT" "$tty" setsid $me_DIR/$me_FILE child "$tty" "$@" & $DEBUG && [[ "$tty" != "not a tty" ]] && echo "PARENT OUT" >$tty exit 0 fi ##### RUNS AFTER CHILD FORKS (actually, on Linux, clone()s. See strace --------------> # 3. We have been reforked. Go to work. exec >/tmp/outfile exec 2>/tmp/errfile exec 0</dev/null shift; tty="$1"; shift $DEBUG && print_debug "*** DAEMON" "$tty" # The real stuff goes here. To exit, see fun (above) $DEBUG && [[ "$tty" != "not a tty" ]] && echo NOT A REAL DAEMON. NOT RUNNING WHILE LOOP. >$tty $DEBUG || { while true; do echo "Change this loop, so this silly no-op goes away." >/dev/null echo "Do something useful with your life, young man." >/dev/null sleep 10 done } $DEBUG && [[ "$tty" != "not a tty" ]] && sleep 3 && echo "DAEMON OUT" >$tty exit # This may never run. Why is it here then? It pretty. # Kind of like, "The End" at the end of a movie that you # already know is over. It always nice.
The result looks like this when DEBUG set to true . Notice how the session ID and process group numbers (SESS, PGID) change:
<shell_prompt>$ bash blahd *** PARENT, PID 5180 PID SESS PGID 5180 1708 5180 /dev/pts/6 PARENT OUT <shell_prompt>$ *** CHILD, NEW SESSION, NEW PGID, PID 5188 PID SESS PGID 5188 5188 5188 not a tty CHILD OUT *** DAEMON, PID 5198 PID SESS PGID 5198 5188 5188 not a tty NOT A REAL DAEMON. NOT RUNNING WHILE LOOP. DAEMON OUT