В некоторых ответах, получивших наибольшее количество голосов, здесь отсутствуют некоторые важные части того, что делает демона демоном, в отличие от просто фонового процесса или фонового процесса, отделенного от оболочки.
Этот http://www.faqs.org/faqs/unix-faq/programmer/faq/ описывает, что необходимо для работы демона. И этот сценарий Run bash as daemon реализует setsid, хотя он пропускает chdir для root.
Вопрос оригинального плаката был на самом деле более конкретным, чем «Как мне создать процесс-демон с помощью 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