# man systemd.unit
[Unit]
Description=This is a sample
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
ExecStart=<path_to_executable>
# ExecReload=
# ExecStop=
# Restart=no/on-success/on-failure/always
# RestartSec=
# TimeoutStartSec=
# TimeoutStopSec=
# WorkingDirectory=
# User=
# Group=
[Install]
WantedBy=multi-user.target
systemd は init プロセス (カーネル初期化後に生成される最初のユーザプロセス) 実装の一つ。 古くは sysvinit や upstart というものが使われていたが、 それを現代的でいい感じの仕組みに置き換えたものである。
sysvinit はスクリプトを直列に実行する形式だったが、 systemd では可能な限り並列にシステム初期化を進める設計になっている。 依存関係を設定し、それを満たす範囲で可能な限り並列に処理を進める。 また、初期化だけでなくオペレーション中のサービスの起動終了や、 シャットダウン前の準備等も取り扱う。
要は今までちゃんとしたものを作ろうとすると面倒だった部分を
全部いい感じにやってくれるセントラルシステムを作った感じ。
常駐システムを組むならこれに乗っかるのが安全で楽だろう。
設定ファイルの概念を理解するのがやや手間だが 最近は AI が教えてくれるし。
ユーザプロセスの起動までできたら OS 開発完了の気持ちになってしまいがちだが、
本当の作業はここからだからね。
ユーザプロセスが立ち上がってからの実行レベル。
runlevel コマンドで確認できるが、systemd 環境では unknown になるようだ。
systemd 環境では廃止されているっぽい?
RHEL の例。Debian は違ったりする。
/etc/init.d/<SERVICE_NAME> にスクリプトを置いておくと service コマンドから
実行できる。
これは systemd に飛ばす形で互換性維持されているっぽい。
service <SERVICE_NAME> start
systemd で管理される最小単位を Unit と呼ぶ。 Unit にはいくつかのタイプがあり、拡張子で識別される。
.service
.target
.mount.swap.device.socket
/etc/systemd/system/
/usr/lib/systemd/system/
Unit 名はファイル名で表す (<UNIT_NAME>.<TYPE>)。
シンボリックリンクも使用可能で、別名定義に使える。
systemd が起動すると default.target が有効化される。
これは multi-user.target や graphical.target へのシンボリックリンク。
このリンク先を変えることが旧来の “デフォルトランレベルの変更” に相当する。
例
graphical.target <–slink– default.targetmulti-user.targetbasic.targetsysinit.targetsystemd が起動すると、依存関係 に基づいてどの Unit を起動するかを決定する。 ただし、起動順を制御する 順序関係 はまったくの別概念。
Unit 設定ファイル、[Unit] セクションに以下の記述を追加すると定義できる。
Wants=
Require=
Conflicts=
自動起動は [Install] セクションに以下の記述を追加すると行える。
その後、systemctl enable <UnitName> で実際に有効化できる。
WantedBy=
multi-user.target を指定すると、multi-user がこの Unit の起動に
依存するようになるので、システム起動時の自動起動が実現できる。RequiredBy=
依存関係に基づいて起動する Unit が決まったら、順序関係に基づいて起動順が決まる。 順序関係の無いもの同士に関してはなるべく並列化される。
順序関係の定義は [Unit] セクションに以下の記述を追加して行う。
Before=After=クライアントとしてネットワークアクセスを行う場合。
[Unit]
Wants = network-online.target
After = network-online.target
サーバーのように待ち受けるだけの場合。
[Unit]
After = network.target