systemd についての Tips

create
2021年10月31日
update
2021年10月31日

前回の記事を書く際に調べた systemd についての備忘録。

🚀覚えておくと便利そうな systemctl サブコマンド

Table 1. systemctl サブコマンドの一部
Command Desc

systemctl --state=failed

失敗したユニットを表示する。

systemctl list-unit-files

すべてのユニットファイル一覧を表示する。

systemctl cat <ユニット>

指定したユニットのファイル内容を表示する。

systemctl edit <ユニット>

指定したユニットのドロップインファイル[1]を編集する。

systemctl edit --force --full <ユニット>

指定したユニットファイル自体を編集する。
ユニットファイルが存在しない場合は新規作成される。

systemctl revert <ユニット>

systemctl edit による変更を初期設定に戻す。
(ドロップインファイルは削除される)

systemctl list-dependencies <ユニット>

指定したユニットが依存しているユニットを表示する。

🏃ユーザーモード

systemd はユーザーがログインすると自動的に systemd ユーザーインスタンスを起動し、ユーザーユニットを管理する。
各ユーザーごとの個人設定ができる。

  • systemctl コマンドに --user オプションを付けて操作する(systemctl --user enable <SERVICE>

  • ユーザー・ユニットファイルは一般に $XDG_CONFIG_HOME/systemd/user [2]ディレクトリ以下に配置する。

    systemctl edit --user コマンドからユニットファイルを作成すると自動的に配置されるので、こちらを推奨。

⛰️環境変数

systemd で利用できる環境変数の一覧はここを参照

~/.profile~/.bash_profile などに定義した環境変数は読み込まれないことに注意。
Table 2. 環境変数の一部抜粋
環境変数 説明

$PATH

固定値。/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
(システムが /usr を使わない場合は :/sbin:/bin が追加される)

$USER

ユニットファイル中の User= を設定していれば利用できる。

$HOME

$PIDFILE

PIDファイルのパス。

後述するユニット指定子も参照するといいかも。

独自に設定したい場合

上述のように設定無しで使える環境変数とは別に、独自にカスタマイズした環境変数を設定したい場合は次のような方法がある。

systemd 一般

<環境変数名>=<値> の書式で標準出力するスクリプトを /usr/local/lib/systemd/system-environment-generators/ ディレクトリに配置すればいいみたい。(参考: systemd.environment-generator(7) — Arch manual pages

スクリプトファイル名には起動順序用の数値を接頭辞につけることが推奨される(例: 50-hoge.sh)。

ユーザーモード限定

~/.config/environment.d//etc/environment.d/ ディレクトリに環境変数を記述した .conf ファイルを配置する(参考: environment.d(5) — Arch manual pages)。

この .conf ファイルには行ごとに <環境変数名>=<値> の書式で記述する。
またファイル名には起動順序用の数値を接頭辞につけることが推奨される(例: 60-foo.conf)。

ユニットファイルごと

Environment=EnvironmentFile= 設定で指定する(参考: systemd.exec(5) — Arch manual pages)。

🍞テンプレートユニット

メリット

ユニットファイルをテンプレートユニットとして定義すると、インスタンス名 と呼ばれる引数によってパラメータ化できる。
つまり、1つのユニットファイルから動作が異なる複数のユニットを起動できる。

定義方法

テンプレートユニットとして定義するには、ユニットファイル名の末尾(拡張子の直前)に @ 記号をつける。
このユニットファイルの中で インスタンス名%i 指定子を使って参照する。

systemctl edit --force --full template-sample@.service
[Unit]
Description=Unit-Template sample

[Service]
Type=simple
ExecStart=/bin/bash -c 'echo %i'    (1)

[Install]
WantedBy=multi-user.target
1 インスタンス名 を返すだけの処理。
使い方

テンプレートユニットからユニットを開始するとき、ユニット名には インスタンス名@ 記号の直後に挿入する。
書式は <ユニット名>@<インスタンス名>.service のようになる。

systemctl start template-sample@hogehoge.service
journalctl --unit template-sample@hogehoge.service
Oct 26 20:46:15 raspberrypi systemd[747]: Started Unit-Template sample.
Oct 26 20:46:15 raspberrypi bash[26263]: hogehoge   (1)
Oct 26 20:46:15 raspberrypi systemd[747]: template-sample@hogehoge.service: Succeeded.
1 インスタンス名 が引数として使われている。

🥨ユニット指定子

ユニットファイルが読み込まれるときに置換される指定子。
指定子の一覧についてはここを参照
下表はそのうちのよく使いそうな一部。

Table 3. 指定子の一部
指定子 対象 説明

%E

設定ファイルの
ルートディレクトリ

system/etc
user$XDG_CONFIG_HOME [2]

%h

ユーザー[3]
ホームディレクトリ

system/root
user$HOME

%i

インスタンス名

ユニットの @ 記号から拡張子までの文字列

%T

一時ディレクトリ

/tmp または $TMPDIR, $TEMP, $TMP

%u

ユーザー名[3]

systemroot
user$USER

%%

パーセント記号

パーセント記号(%)を記述したい場合

XDG Base Directory の仕様については XDG Base Directory - ArchWiki に概要がまとめられていてわかりやすい。

🖨️ systemd.service

スクリプトを実行する場合はたいてい simpleoneshot を使えばよさそう。

simple と oneshot

使い分け
simple

プロセスが起動した時点でサービスが開始されたとみなされ、後続のサービスが開始される。

  • サービスを並列実行させたい場合

  • サービスが長時間実行される場合

oneshot

ExecStart= で指定したコマンドの実行完了後にユニットが開始されたとみなす。

  • コマンド完了後に後続サービスを実行したい場合

どっちでもいいならデフォルト推奨の simple を使うのが良さそう。

1. 変更・上書きしたい設定だけを記述したファイル。
2. デフォルト → $HOME/.config/systemd/user 。
3. ここでのユーザーとは systemd 実行者のこと。Service セクションの User= 設定は影響しない。