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 startPri 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/goprogramNasimulujme 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/goprogramSupervisor detekol, že supervisovaný program s pôvodným pid 49037 skončil a reštarvoval ho. Nová inštancia dostala pid 49691.