Linux
systemd

systemdの*.serviceファイルの書き方

More than 3 years have passed since last update.

たまに書く必要があったりするのでめも。環境はArch Linux。

まず基本的なところで前に自分で書いた/etc/systemd/system/kdump.serviceを元に。

kdump.service
[Unit]
Description=Load dump capture kernel
After=local-fs.target

[Service]
Type=oneshot
ExecStart=/opt/bin/run-kexec.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

ファイルの基本構成要素は UnitServiceInstall から成り立っていて UnitInstall はman 5 systemd.unit、 Service はman 5 systemd.serviceに詳細な説明があります。
UnitInstall はユニットファイルの共通的な設定内容、 Service はそのサービスを実行するためというような感じになってます。

Unitセクション

Description

ユニットの説明を書く。

After/Before

After(Beforeも)は指定したユニットの実行順番の依存関係を設定する。例えばfoo.serviceで↓のように書いていたらfoo.serviceはbar.serviceのstart-up処理が終わるまで起動しない。

After=bar.service

Requires/Wants

ユニットの依存関係の定義。RequiresとWantsの大きな違いとしてリストアップした依存関係のユニットが失敗したときの処理が違う。foo.serviceで↓のように書いた場合、bar.serviceの起動に失敗してもfoo.serviceのstartup処理そのものが失敗になる訳ではない(もちろんfoo.serviceを起動する上でbarが必要ならだめだけど)。

Wants=bar.service

その他

man 5 systemd.unit

Serviceセクション

Type

Typeには以下の5があり、設定がなければsimpleがデフォルトで使われる。

  • simple
  • forking
  • oneshot
  • notify
  • dbus

kdump.serviceの場合はoneshotを使っていて、これはコマンドとしてはすぐに終わるような場合に使う。

ExecStart

実行するコマンドラインを書く

RemainAfterExit

Typeがoneshotの場合はコマンドの実行終了後もステータスをアクティブにしておきたいのでRemainAfterExit=yesとしてsystemdにこのユニットはアクティブですよーと知らせる。

kdumpの例

kdumpの例だとTypeはoneshot、RemainAfterExitにyesを設定し、こんなスクリプトを実行してます。

#!/bin/bash

kernname=`uname -r`
boot_dir=/boot
vmlinuz="$boot_dir/vmlinuz-$kernname"
initramfs="$boot_dir/initramfs-$kernname.img"
root_dev=`cat /proc/cmdline  | sed 's/ /\n/g' | grep ^root= | cut -f2- -d'='`

echo /usr/bin/kexec -p "$vmlinuz" --initrd="$initramfs" --append="root=$root_dev single irqpoll maxcpus=1 reset_devices"
/usr/bin/kexec -p "$vmlinuz" --initrd="$initramfs" --append="root=$root_dev single irqpoll maxcpus=1 reset_devices"
echo "kexec comman executed"

exit 0

sshdの例

sshdの場合はプロセスの再起動、終了なんかの設定も入ってます。

[Service]
ExecStart=/usr/bin/sshd -D
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=always

その他

man 5 systemd.service

Installセクション

WantedBy/RequiredBy

systemctl enable XXXでユニットをenableしたときに.wants、.requiresにシンボリックリンクを作る。 動作としてはWants=、Requires=と同じような感じ。

実際にこんな感じになってます。

masami@saga:~$ ls -la /etc/systemd/system/multi-user.target.wants/
total 8
drwxr-xr-x 2 root root 4096 Dec  4 14:13 .
drwxr-xr-x 4 root root 4096 Dec  4 14:13 ..
lrwxrwxrwx 1 root root   38 Nov  1 01:53 dhcpcd.service -> /usr/lib/systemd/system/dhcpcd.service
lrwxrwxrwx 1 root root   33 Nov  5 12:14 kdump.service -> /etc/systemd/system/kdump.service
lrwxrwxrwx 1 root root   40 Nov  1 10:27 libvirtd.service -> /usr/lib/systemd/system/libvirtd.service
lrwxrwxrwx 1 root root   36 Dec  4 14:13 ntp-once.service -> /etc/systemd/system/ntp-once.service
lrwxrwxrwx 1 root root   40 Oct 21 22:27 remote-fs.target -> /usr/lib/systemd/system/remote-fs.target
lrwxrwxrwx 1 root root   36 Nov  1 07:45 sshd.service -> /usr/lib/systemd/system/sshd.service

その他

man 5 systemd.unit