V tomto krátkom blogu vám ukážem ako vytvoriť rc.d script pre Go program, ktorý má bežať na pozadí ako daemon. A aby to bolo zaujímavejšie, tento daemon bude supervizovaný, t.j. v prípade, že z nejakého dôvodu príde k ukončeniu programu (napr. chybou), bude Go program znovu spustený.
Na úvod odporúčam prečítať si (excelentnú) dokumentáciu k FreeBSD rc.d scriptingu. FreeBSD rc.d script je spravidla veľmi jednoduchý /bin/sh
script. To čo umožňuje rc.d scriptom zostať jednoduchými je rc.subr framework, ktorý sa postará o zložité veci, ako napr. riadenie závislostí medzi rc.d scriptami.
So samotným rc.subr
vystačíme v majorite prípadov, my ale chceme daemon-a supervízovať, siahneme preto ešte po daemon utilite, ktorá nám to umožní.
Pozrime sa na ukážkový rc.d
script. Keďže používame /usr/sbin/daemon
utilitu na manažovanie životného cyklu daemon-a, nemôžeme sa spolahnúť na rc.subr
, jeho mechanizmus vytvorenia pid
súboru a procedúr start
, stop
a status
. Tieto 3 obslužné procedúry si musíme napísať sami.
Jadrom rc.d scriptu je procedúra goprogram_start
a /usr/sbin/daemon -P ${pidfile} -r -f -u $goprogram_user $command
, kde je povedané, že chceme vytvoriť rodičovský pid
súbor (prepínač -P /var/run/goprogram.pid
), pri skončení goprogram
ho chceme reštartovať (prepínač -r
) a chceme, aby bežal pod používateľom goprogram
(prepínač -u goprogram
). Procedúry goprogram_stop
a goprogram_status
musia používať vytvorený pid
súbor.
#!/bin/sh
#
# PROVIDE: goprogram
# REQUIRE: networking
# KEYWORD:
. /etc/rc.subr
name="goprogram"
rcvar="goprogram_enable"
command="/usr/local/goprogram/goprogram"
goprogram_user="goprogram"
pidfile="/var/run/${name}.pid"
start_cmd="goprogram_start"
stop_cmd="goprogram_stop"
status_cmd="goprogram_status"
goprogram_start() {
/usr/sbin/daemon -P ${pidfile} -r -f -u $goprogram_user $command
}
goprogram_stop() {
if [ -e "${pidfile}" ]; then
kill -s TERM `cat ${pidfile}`
else
echo "${name} is not running"
fi
}
goprogram_status() {
if [ -e "${pidfile}" ]; then
echo "${name} is running as pid `cat ${pidfile}`"
else
echo "${name} is not running"
fi
}
load_rc_config $name
: ${goprogram_enable:=no}
run_rc_command "$1"
Pred použitím scriptu nezabudnite na chmod +x /usr/local/etc/rc.d/goprogram
a pridanie goprogram_enable="YES"
do /etc/rc.conf
.
Poďme vyskúšať náš nový rc.d script. Najskôr spustíme novovytvoreného daemon-a:
service goprogram start
Pri pohľade na bežiace procesy vidíme, že beží supervisor aj supervisovaný program:
ps aux
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
root 49036 0.0 0.0 10468 1640 - SsJ Mon11 0:00.06 daemon: /usr/local/goprogram/goprogram[49037] (daemon)
goprogram 49037 0.0 0.0 41572 12840 - IJ Mon11 0:42.54 /usr/local/goprogram/goprogram
Nasimulujme chybu programu a pozrime sa čo sa stane:
kill -9 49037
ps aux
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
root 49036 0.0 0.0 10468 1644 - SsJ Mon11 0:00.07 daemon: /usr/local/goprogram/goprogram[49691] (daemon)
goprogram 49691 0.0 0.0 30940 8788 - SJ 09:54 0:00.01 /usr/local/goprogram/goprogram
Supervisor detekol, že supervisovaný program s pôvodným pid 49037 skončil a reštarvoval ho. Nová inštancia dostala pid 49691.