systemd 操作マニュアル

10 分で読了
このページの目次

稼働状態、起動の可否、起動時の依存関係への登録を分けて考える。例はシステムの example.service。ユーザーサービスは --user を付け、別のマネージャーとして確認する。

やりたいこと参照先
サービスが起動しない状態と根拠
自動起動・起動禁止稼働と有効化
設定や起動コマンドを変更設定の反映範囲
定期実行とログタイマーと検証

状態から終了理由を調べる

一つのサービスを確認する

# unit の場所・実行状態・最近のログを読む
systemctl status example.service --no-pager

--no-pager は直接出力。Loaded の場所・エラーから Active と主プロセスへ読む。非 active では非ゼロ終了する場合があり、問い合わせ失敗とは限らない。

# 実行・終了結果・有効化のプロパティを照合する
systemctl show example.service -p ActiveState -p SubState -p Result -p ExecMainStatus -p UnitFileState

ActiveState=failed と Result=exit-code はプロセスの失敗を示す。ExecMainStatus は主プロセスの値であり、起動段階によって ExecStartPre なども調べる。

# 今回の起動における unit の最近のログを読む
journalctl -u example.service -b -n 80 --no-pager

-u は unit、-b は今回の起動、-n は行数。前回の起動は -b -1、追跡表示は -f を選ぶ。

個別診断と全体一覧を分ける

# failed と記録された unit を列挙する
systemctl --failed

原因修正後、必要なら sudo systemctl reset-failed example.service で失敗状態と起動制限カウンターを消す。設定修復やアプリ起動は行わない。

# 非アクティブも含め、ロード済みサービスを表示する
systemctl list-units --all --type=service

ディスク上の unit ファイルと有効化状態は systemctl list-unit-files --type=service。ロード済み集合とファイル一覧は範囲が異なる。

観察意味次の確認
active (running)プロセスは稼働中。業務の正常性は別待ち受けと実際のリクエスト
active (exited)RemainAfterExit を使う oneshot などType、ExecStart、終了結果
failed / exit-code失敗を記録。reset-failed は原因を直さないjournal と Result を確認
not-foundこのマネージャーには unit がない名前、配置先、--user の要否

稼働状態と有効化は別の軸

図を準備しています
稼働と自動起動は別の軸

start/stop は稼働、enable/disable は起動 link を変更する。mask は以後の起動を拒否するが既存 process を止めない。

目的systemctl効果
今すぐ起動・停止start / stop現在の稼働状態を変更
ターゲット経由の起動登録・解除enable / disable[Install] のリンクを管理。単独では起動・停止しない
両方を実行enable --now / disable --now登録と稼働の両方を変更
通常の起動要求を禁止mask / unmaskmask は /dev/null を指す。稼働中の停止は別

現在の実行状態だけを変える

# サービスの即時起動を要求する
sudo systemctl start example.service

systemctl is-active example.service と実リクエストで確認する。停止は別途 sudo systemctl stop example.service。起動時の有効化は解除されない。

target 経由の起動を設定する

# Install に従い起動リンクを作る。今は起動しない
sudo systemctl enable example.service

is-enabled で確認する。同時に起動するなら enable --now。解除だけなら disable、停止もするなら disable --now を選ぶ。

mask の前に起動経路を調べる

# ロード済み unit の逆依存を確認する
systemctl list-dependencies example.service --reverse

--reverse を外すと依存先を表示する。socket / timer も調べる。未ロード unit 全体の静的解析ではない。起動を禁止するときだけ sudo systemctl mask example.service、解除は unmask。is-enabled で確認する。

disabled でも手動、依存関係、socket、timer から起動できる。static は通常 [Install] 情報を持たない。ローカルの unit ファイルがあると mask が競合する場合があり、上書きせず確認する。

unit ファイルかアプリ設定か

変更操作検証
unit / drop-in を手動編集daemon-reloadshow で解析値を確認。新プロセス設定には再起動が必要
アプリ自身の設定reloadreload 対応が必要。接続への影響はアプリ次第
プロセスを作り直すrestart停止後に起動するため中断を考慮

全設定を読んでから上書きを追加する

# 元 unit と drop-in の出典を表示する
systemctl cat example.service

元の値と場所を記録し、配布元管理のファイルを直接編集しない。cat はディスク上、show は管理器が読み込んだ値を示す。

# ローカルの drop-in を作成・編集する
sudo systemctl edit example.service

エディターで有効な領域に次の Service 断片を書いて保存する。取消は保存せず終了。戻す場合は今回の drop-in だけを復元・削除し、reload / restart で確認する。他の上書きは残す。

[Service]
Environment=LOG_LEVEL=debug
Restart=on-failure
RestartSec=5s

systemctl edit の保存成功後は通常 unit 定義が自動再読込される。手動編集では daemon-reload が必要。ExecStart の置換は空の代入で旧値を消してから新コマンドを指定し、実際のサービス引数を保持する。

手動編集後に検証・読込する

# ローカル unit の構文と解決可能な依存を検証する
systemd-analyze verify /etc/systemd/system/example.service

cat で主 unit の実際の場所を確認する。edit しても /etc に完全な主ファイルがあるとは限らない。エラーを先に直す。アプリ独自設定の検証は別である。

# 手動編集した unit 定義を管理器に読み込ませる
sudo systemctl daemon-reload

サービスのプロセスは再作成しない。通常、systemctl edit の保存時には相当の処理が済んでいる。

# 管理器が解釈した主要設定を確認する
systemctl show example.service -p ExecStart -p Environment -p Restart

正しいことを確認し、新プロセスが必要なら restart 後に status / journal と実リクエストを確認する。reload 対応のアプリ設定だけなら sudo systemctl reload example.service を選ぶ。両方を機械的に続けない。

ユーザー管理器の状態は別に確認する

# 対象ユーザーのセッションでユーザーサービスを確認する
systemctl --user status example.service --no-pager

通常は ~/.config/systemd/user/ に配置する。同じユーザーで edit / daemon-reload / enable --now を行い、journalctl --user -u example.service を読む。sudo で root 側へ対象を変えない。

ユーザーサービスは systemctl --user と journalctl --user を使う。未ログインでもユーザーマネージャーを動かす必要がある場合に loginctl enable-linger USER を検討する。個別サービスの enable とは別である。

タイマー:起動条件と実行結果

# /etc/systemd/system/example.timer
[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=30s

[Install]
WantedBy=timers.target
# /etc/systemd/system/example.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/example-task

実行するプログラムを用意してから timer を有効にする。Persistent は OnCalendar に適用され、停止中に逃した実行を再有効化時に一度補える。全回分の再実行ではない。OnBootSec、OnUnitActiveSec は単調時計に基づく。

日時式と対応 unit を検証する

# daily の解釈と次の実行時刻を確認する
systemd-analyze calendar daily

タイムゾーンと時刻を確認する。実際の OnCalendar 式に置き換えられる。systemd-analyze verify で timer と service の両方を検証し、実行ファイルも確認する。

# 作成した timer と service を読み込む
sudo systemctl daemon-reload
# service の手動実行ではなく timer を有効化・起動する
sudo systemctl enable --now example.timer

Persistent による補完実行が起動後に起き得るため、繰り返し実行時の挙動を確認しておく。

# NEXT・LAST・起動対象サービスを確認する
systemctl list-timers --all

NEXT は予定、LAST は起動であり成功記録ではない。service の journal と Result / ExecMainStatus を確認する。調度停止は sudo systemctl disable --now example.timer。実行中の処理は別に扱う。

起動時間とログ容量を別々に調べる

# 時間上クリティカルな依存関係を確認する
systemd-analyze critical-chain example.service

journal の時刻と照合する。並列起動やサービス種別で時間の解釈は変わる。

# 保持方針を決める前に journal 使用量を測る
journalctl --disk-usage

削除が必要なら sudo journalctl --rotate で現在分を閉じ、別途 --vacuum-time=7d で古いアーカイブを削除する。必要な記録は先に保存する。継続的な容量制御は journald の SystemMaxUse などで設定する。

timer の active は前回処理の成功を示さない。service の Result とログを確認する。journalctl の vacuum はアーカイブログが対象で、総使用量の上限ではない。blame の順位だけで起動の律速も判断できない。

systemctl · systemd.timer · journalctl