A algunas de las respuestas votadas aquí les faltan algunas partes importantes de lo que hace que un demonio sea un demonio, en lugar de un proceso en segundo plano o un proceso en segundo plano separado de un shell.
Este http://www.faqs.org/faqs/unix-faq/programmer/faq/ describe lo que se necesita para ser un demonio. Y este script Ejecutar bash como demonio implementa el setid, aunque pierde el chdir a la raíz.
La pregunta del póster original era en realidad más específica que "¿Cómo creo un proceso de demonio usando bash?", Pero dado que el tema y las respuestas discuten la demonización de los scripts de shell en general, creo que es importante señalarlo (para intrusos como yo que investigan el finos detalles de la creación de un demonio).
Aquí está mi interpretación de un script de shell que se comportaría de acuerdo con las preguntas frecuentes. Configure DEBUG en true
para ver una salida bonita (pero también sale inmediatamente en lugar de recorrer un bucle sin fin):
#!/bin/bash
DEBUG=false
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
}
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 /
if [ "$1" = "child" ] ; then
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
if [ "$1" != "XXrefork_daemonXX" ] ; then
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
exec >/tmp/outfile
exec 2>/tmp/errfile
exec 0</dev/null
shift; tty="$1"; shift
$DEBUG && print_debug "*** DAEMON" "$tty"
$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 padawan." >/dev/null
sleep 10
done
}
$DEBUG && [[ "$tty" != "not a tty" ]] && sleep 3 && echo "DAEMON OUT" >$tty
exit
La salida se ve así cuando DEBUG
se establece en true
. Observe cómo cambian los números de ID de grupo de proceso y sesión (SESS, PGID):
<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