У деяких із запропонованих тут відповідей відсутні деякі важливі частини того, що робить демон демоном, на відміну від простого фонового процесу або фонового процесу, від'єднаного від оболонки.
Цей http://www.faqs.org/faqs/unix-faq/programmer/faq/ описує, що необхідно, щоб бути демоном. І цей скрипт запуску bash як демон реалізує setid, хоча він втрачає кореневий chdir.
Питання оригінального плаката насправді було більш конкретним, ніж "Як створити процес демона за допомогою bash?", Але оскільки тема та відповіді обговорюють демонізацію сценаріїв оболонки загалом, я вважаю важливим вказати на це (для таких осіб, як я, які вивчають дрібні деталі створення демона).
Ось моє виконання сценарію оболонки, який би поводився відповідно до FAQ. Встановіть DEBUG, щоб true
бачити гарний результат (але він також виходить негайно, а не циклічно):
#!/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
Результат виглядає так, коли DEBUG
встановлено значення true
. Зверніть увагу на те, як змінюються номери сеансу та ідентифікатора групи процесів (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