systemd serviceの概要・基礎知識
systemdは現代の主要なLinuxディストリビューション(Ubuntu・Debian・RHEL系・Arch等)が採用するinitシステムで、サーバープロセスやバッチジョブを「ユニット」と呼ばれる単位で管理します。本ツールはWebアプリやワーカーを常駐化する際に必要な「.service」ユニットファイルを、Description・ExecStart・User・Restart・PrivateTmp等のフォーム入力からまとめて生成します。手書きで起きがちな構文ミス([Service]忘れ・改行抜け・パスの相対指定)を防ぎ、/etc/systemd/system/に置いてすぐ使える形で出力する設計です。本番運用に必要なセキュリティオプション(PrivateTmp / ProtectSystem / リソース制限)にも対応しています。
セクションと主要ディレクティブ
| セクション | ディレクティブ | 役割 |
|---|---|---|
| [Unit] | Description / After / Wants | 説明と起動順序 |
| [Service] | Type / ExecStart / User / Group | プロセス起動方法 |
| [Service] | Restart / RestartSec | 異常終了時の再起動制御 |
| [Service] | Environment / EnvironmentFile | 環境変数の注入 |
| [Service] | PrivateTmp / ProtectSystem | セキュリティ強化 |
| [Install] | WantedBy | 有効化時の依存先 |
Typeの選択は重要で、simpleは最も汎用、forkingは古典的なデーモン、oneshotは単発スクリプト、notifyはsd_notify()対応アプリで使い分けます。
使い方の流れ
- [Unit]セクションでDescription(サービス説明)と After(依存サービス。通常は
network.target)を入力します。Wantsは「望ましい依存」で、network-online.targetを指定するとオンライン到達後に起動します。 - [Service]セクションでTypeを選び、ExecStartにフルパスで起動コマンドを書きます。例:
/usr/bin/node /opt/myapp/index.js。User・Group・WorkingDirectoryも本番では明示が推奨です。 - 環境変数は
KEY=VALUEを改行区切りで入力するか、別ファイル(EnvironmentFile)で外部化します。秘密値は専用ファイル+chmod 600が原則です。 - Restartはサーバー系なら
always、バッチ系ならon-failureを選び、RestartSecで再試行間隔(秒)を指定します。 - 「生成する」を押すとユニットファイル本体と、設置・有効化用のコマンド(
cp / daemon-reload / enable / start)がまとめて出力されます。
こんな場面で使う
- 自作Webアプリの常駐化:Node.js / Pythonで作ったサーバーをVPS上で永続稼働させ、再起動時に自動立ち上げするユニットを素早く整備できます。
- バッチジョブの自動再試行:Type=oneshot+Restart=on-failureで、cronより細かい挙動制御を実現できます。
- 本番セキュリティ強化:PrivateTmp / ProtectSystem / NoNewPrivileges 等を有効にしたテンプレートで、セキュリティ要件をテンプレ化できます。
- OSSのインストールガイド作成:READMEに「以下のserviceファイルを作成してください」と貼れる、一貫したフォーマットを提供できます。
- Ansible/Chefのテンプレート整備:構成管理ツール向けJinja2テンプレートの土台として、生成結果を流用できます。
使う前に知っておきたい注意点
- ユニットファイルは必ず
/etc/systemd/system/に配置し、sudo systemctl daemon-reloadで再読み込み後にenable / startします。Read-onlyの/lib/systemd/system/には置かないでください(パッケージで上書きされる恐れ)。 - ExecStartは絶対パス指定が必須です。
node app.jsのような相対指定は失敗します。which nodeでフルパスを確認してください。 - シェルパイプやリダイレクトは直接書けません。
bash -c "..."でラップするか、ログをsyslog経由(StandardOutput=journal)で扱うのが正攻法です。 - Restart=alwaysは強力ですが、起動直後に毎回失敗するアプリだと無限再起動ループになります。
StartLimitIntervalSec/StartLimitBurstでブレーキも併用してください。 - ProtectSystem=fullは
/usrと/bootを読み取り専用化します。アプリが書き込みを必要とするディレクトリはReadWritePaths=で許可リストに追加してください。
用語の補足
- journal:systemdのログ統合機能。
journalctl -u myapp.service -fでリアルタイム追跡できます。 - target:複数ユニットの依存関係をまとめる単位。
multi-user.targetはいわゆる「マルチユーザー起動状態」です。 - drop-in:
/etc/systemd/system/myapp.service.d/に置く設定追加ファイル。元ファイルを直接編集せずに上書き設定できます。