由 init 到 systemd

By | March 23, 2017

在電腦世界,雖要有一些程式來管理其他程式的「啟動」、「重啟」及「停止」。

在 Windows、Linux、Matrix 🙂 都有。Windows 叫這做 “Services”。開放的 Linux 就有數種程式來做這種事。比較常用的就有 init、upstart 及 systemd。

現在知名的發行版,如 Fedora、RHEL、Ubuntu、Debian 都已把 init 改為用 systemd。這個轉換早前引發開源界很大爭議,原因 systemd 有違 Unix Philosophy:

  • Write programs that do one thing and do it well.
  • Write programs to work together.
  • Write programs to handle text streams, because that is a universal interface

Systemd 做太多野了,不單啟動或重啟一個程式這樣簡單。Systemd 不是純 text process。對一般 users 來說 systemd 好處的確大過缺點,特別能並行啟動開機程式,令開機時間大大縮短,另外很多 software 如 GNOME3 依賴 systemd,所以好多發行版都改用了 systemd。

來看 init script,通常它是 BASH script,含有 programming 元素,用 case 來選擇 start、stop 及 restart command,而 restart 通常只是 stop 後再 start。

[bash]
start(){
# …
}

stop(){
# …
}

case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
sleep 2
start
;;
*)
echo "Usage: $0 {start | stop | restart}"
esac
[/bash]

而 systemd script 則簡單得多,沒有 programming 元素,以 gorush 為例子,systemd script 就是這麼簡單易明。
[shell]
[Unit]
Description=A push notification micro server using Gin framework written in Go.
After=network.target

[Service]
# Run Grunt before starting the server (optional)
#

# Start the js-file starting the express server
ExecStart=/usr/local/bin/gorush -c /etc/gorush/gorush.yaml
WorkingDirectory=/var/lib/gorush
Restart=always
RestartSec=5
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=gorush
# Change to a non-root user (optional, but recommended)
User=gorush
Group=gorush
# Set environment options
#Environment=

[Install]
WantedBy=multi-user.target
[/shell]

把以上 script 放去 /lib/systemd/system/gorush.service 再用 systemctl 設定便可。

$ sudo systemctl daemon-reload
$ sudo systemctl enable gorush
$ sudo systemctl start gorush

最後,systemd 令人興奮的是,以往我們可能需要家一個 crontab 來不斷 monitor 個 process 有沒有掛掉,這個 systemd 都幫我們做了。

Restart=always

就是當 process 無論哪種原因,自然或不正常掛掉,都會 restart。除了 always,還有 no、on-success、on-failure、on-abnormal、on-abort、on-watchdog,詳細可看這裡