systemd サービスユニット設定の完全ガイド

systemd におけるサービス管理の核心は .service ユニットファイルにあります。この設定ファイルは、プロセスの起動方法、ライフサイクル制御、依存関係、リソース制限などを宣言的に定義します。以下に、実践で最も頻繁に使用される構成要素を再構成・要約し、誤解を招きやすいポイントを明確に解説します。

基本構造

すべてのサービスファイルは以下の3つのセクションから構成されます:

  • [Unit]:ユニットのメタデータと他のユニットとの依存関係(例:After=network.target, Wants=redis.service
  • [Service]:実行ロジックの本体(Type, ExecStart, Restart など)
  • [Install]:有効化時の振る舞い(WantedBy=multi-user.target

重要な Type 値の選択基準

Type= はサービスの起動モデルを決定する最重要パラメータです。用途に応じて以下のいずれかを選択します:

Type 適用ケース 注意点
simple(デフォルト) 長時間実行されるが、初期化完了を通知しないアプリケーション(例:静的Webサーバ) 起動直後に「アクティブ」と判断されるため、IPCチャネルが準備できていない場合に依存サービスが失敗する可能性あり
notify systemd へ初期化完了を明示的に通知できるサービス(C/Go/Python で sd_notify("READY=1") を実装) NotifyAccess=main を併記推奨。非対応アプリには利用不可
forking 従来型のUNIXデーモン(fork() 後、親プロセスが即座に終了) PIDFile= の指定が強く推奨。未指定時は systemd がPIDを推定するため信頼性が低下
dbus D-Bus システムバス上で名前を取得するサービス BusName=org.example.MyService を必須指定。自動的に dbus.socket への依存が追加される
oneshot 起動時に一度だけ実行して終了するスクリプト(例:初期化処理、クリーンアップ) RemainAfterExit=yes を併用すると、実行後も「アクティブ」状態を維持可能

実行制御のキーオプション

以下の設定は、サービスの可用性と信頼性を左右します:

  • ExecStart=:メイン実行コマンド。絶対パス推奨(例:/usr/local/bin/myapp --config /etc/myapp.conf
  • ExecStartPre=:起動前に実行(例:ディレクトリ作成、権限チェック)。失敗時は起動中止
  • ExecStop=:停止時に実行。非同期なシグナル送信(kill -TERM $MAINPID)ではなく、同期的な終了待機が必須(例:timeout 30s /usr/bin/myappctl shutdown
  • Restart=on-failure:障害発生時の自動復旧に最適。ただし、StartLimitIntervalSec=StartLimitBurst= で再起動頻度を制限すること
  • TimeoutStartSec=60:起動タイムアウト。特に Type=notify の場合は、初期化遅延に対応するため必要

環境変数とコマンド構文の注意点

コマンドラインではシェル構文(パイプ・リダイレクト・バックグラウンド実行)は一切サポートされません。必要な場合は明示的にシェルを呼び出します:

# ✅ 正しい(sh 経由でパイプ実行)
ExecStart=/bin/sh -c 'journalctl -u nginx | grep "error" | wc -l'

# ❌ 間違い(systemd が解釈できない)
ExecStart=journalctl -u nginx | grep "error"

環境変数展開には2種類があります:

  • $VAR:空白区切りで複数引数に分割(例:Environment="ARGS=--debug --port 8080"$ARGS は3つの引数になる)
  • ${VAR}:そのまま1つの引数として扱われる(例:${ARGS} は1つの引数 --debug --port 8080

実践サンプル:安全な oneshot サービス

システム起動時に一度だけ実行し、その後も「有効」と認識させたいケース:

[Unit]
Description=Initialize database schema
After=postgresql.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/db-migrate --env production
ExecStop=/usr/local/bin/db-rollback --env production
SuccessExitStatus=0 2

[Install]
WantedBy=multi-user.target

この設定では、systemctl start db-init.service を実行するとマイグレーションが走り、その後は「アクティブ」状態が維持されるため、再度実行しても無視されます。

リソース制御と監視の拡張

信頼性向上のため、以下の高度な機能も活用できます:

  • WatchdogSec=30:30秒ごとに sd_notify("WATCHDOG=1") を要求。応答がないと自動再起動
  • MemoryMax=512M:cgroup v2 によるメモリ上限(systemd.resource-control(5) 参照)
  • OOMPolicy=stop:OOM 発生時にサービス全体をクリーンに停止

設定変更後は必ず検証を行います:sudo systemctl daemon-reload && sudo systemctl cat myapp.service で構文エラーを確認し、sudo systemctl verify myapp.service で整合性をチェックしてください。

タグ: systemd linux service-management

6月25日 21:20 投稿