systemdユニットの基本と再起動戦略|最小雛形と安全なRestart=設計

定期実行・ジョブ

本番で落ちないサービス運用のために、最小限の systemd ユニットを用意しつつ、RestartStartLimit* を組み合わせた安全な再起動戦略を一気に整えます。この記事を読めば、雛形に必要なキーとフラッピング回避の設計まで最短でセットできます。

詳細な流れを横断的に確認したい場合は Linuxトラブルシューティング総合ハブ から全体像をご覧いただけます。

まずはこの雛形:Restart=前提の安全設計テンプレ

最短で迷わず使える最小ユニット雛形です。再起動戦略は結論として「Restart=on-failureRestartSecで間隔を置き、StartLimitでフラッピング抑制」を標準にします。

# /etc/systemd/system/myapp.service
[Unit]
Description=My App
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=300
StartLimitBurst=5

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/srv/myapp
ExecStart=/srv/myapp/bin/start
ExecStop=/srv/myapp/bin/stop
Restart=on-failure
RestartSec=5s
SuccessExitStatus=0 143
RestartPreventExitStatus=23
TimeoutStopSec=30s
KillMode=control-group

[Install]
WantedBy=multi-user.target

Restart=on-failureとRestartSec=でのリトライ間隔

Restart=on-failure異常終了・シグナル終了時のみ自動再起動します。常時ループの危険が減り、意図的な停止(systemctl stopや正常終了コード)では再起動しません。
RestartSec=5sは再起動のクールダウンです。短すぎるとCPUやログを浪費するため、まずは5〜10秒を基準にし、起動コストが高いサービスはやや長め(10〜30秒)に伸ばします。

StartLimitInterval=/StartLimitBurst=でフラッピング抑制

StartLimitIntervalSec=300StartLimitBurst=5は、5分で5回以上の再起動が続いたときにユニットを抑止(Start request repeated too quickly.)します。
事故的なクラッシュループを仕組みで強制停止でき、夜間の暴走を防げます。抑止後は原因を直してからsystemctl reset-failed myapp && systemctl start myappで復帰します。

落とし穴と対策:依存関係・停止挙動・退出コードの扱い

再起動戦略が良くても、依存関係停止の作法終了コードの解釈を誤るとsystemdユニットは不安定になります。起動順・ネットワーク待機・丁寧な停止・終了コードの明示をそろえて、再発しない設計に固めます。

After=/Requires=の付け方とネットワーク待機(network-online.target)

After=順序Requires=存在必須の依存です。ネットワーク必須なら次のようにします。

  • 最低限:After=network-online.target + Wants=network-online.target
  • 本気で待つ:systemd-networkd-wait-online.serviceNetworkManager-wait-online.serviceを有効化
    DNSや外部API前提のアプリは、実通信が可能になるまで待つ設計にしないとクラッシュ→再起動ループを誘発します。不要なRequires=多用は起動失敗の連鎖になるため、必要最小限に留めます。

SuccessExitStatus=/RestartPreventExitStatus=で「正常終了扱い」を明示

アプリ都合の終了コードをsystemdにどう見せるかを調整します。

  • SuccessExitStatus=0 143:例)SIGTERM(143)での穏当な終了を成功扱いにする
  • RestartPreventExitStatus=23:例)設定ミス時にexit 23再起動を抑止し、無限ループを避ける
    これにより、Restart=on-failureの判定が意図通りになります。終了コード設計はアプリ側とセットで決めます。

KillMode=/TimeoutStopSec=で停止を丁寧に

停止時はまず穏やかに、必要なら強制が原則です。

  • KillMode=control-group:同一cgroup内の子プロセスまで一括停止。孤児プロセスを残さない
  • TimeoutStopSec=30sExecStop=やアプリのシャットダウンに十分な猶予を与える
  • 併用ヒント:ExecStop=で自前の停止スクリプトを呼び、接続のドレイン一時ファイルのフラッシュを済ませてから終了
    TimeoutStopSecが短すぎるとSIGKILL連発でデータ破損や再同期コスト増につながります。反対に長すぎるとリリース時の足止めになるため、実測で調整します。

本番運用チェックリスト:変更→デーモン再読込→温和なリスタート

ユニット変更時の安全な反映手順を定型化します。最小の停止時間で確実に反映し、初期不安定期はログで挙動を観察します。

daemon-reloadのタイミングとsystemctl reload/restart使い分け

ユニットファイル(.service)やドロップイン/etc/systemd/system/myapp.service.d/*.conf)を編集したら、まずdaemon-reloadで定義を再読込します。

  • 反映の基本:
  1. sudo systemctl daemon-reload
  2. 設定検証:systemd-analyze verify /etc/systemd/system/myapp.service
  3. 温和な反映:systemctl reload myapp(アプリがSIGHUP等で設定再読込に対応している場合)
  4. 非対応なら短時間停止で:systemctl restart myapp
    reload接続を切らずに反映できるのが利点です。restartは確実ですが瞬断が発生します。どちらを採用するかはアプリの実装で決めます。

ログ監視(journalctl -u <unit>)と初期不安定期の観察ポイント

デプロイ直後や設定変更直後は数分間の観察を欠かさないでください。

  • 直近ログ:journalctl -u myapp -b -n 200 -f(起動後の追尾)
  • 再起動ループ検知:systemctl status myappActiveの遷移回数と「Start request repeated too quickly」を確認
  • 退出コードの傾向:journalctl内のcode=exited, status=…signal=をチェック
  • ネットワーク待機の失敗:network-online.target関連やwait-onlineのタイムアウト
  • 資源枯渇:同時にdmesg -Tsudo systemd-cgtopOOM/KILLやcgroup圧迫を確認
    初期の小さなエラーでも、同一パターンがStartLimitにぶつかる前に手当てすることで、夜間の無用なアラートやサービス停止を防げます。

まとめ

systemdの基本を押さえて雛形と再起動戦略を整えれば、サービスは安定して稼働し続けます。Restart=on-failureRestartSecで再起動の間隔を設け、StartLimitでフラッピングを防止し、依存関係や停止挙動まで定義しておくことが安全運用の第一歩です。

本番運用では、daemon-reloadjournalctlでの確認を習慣化し、ユニットが予期せず落ちても被害が広がらないようにします。さらに、デプロイ直後の確認手順を組み合わせれば、障害の芽を早期に摘むことができます。

systemdでの自動再起動設計を固めたら、依存関係管理や監視・通知まで含めてハブ記事を活用し、運用設計を一気に仕上げましょう。

参照リンク

Bash玄

はじめまして!Bash玄です。

エンジニアとしてシステム運用に携わる中で、手作業の多さに限界を感じ、Bashスクリプトを活用して業務を効率化したのがきっかけで、この道に入りました。「手作業は負け」「スクリプトはシンプルに」をモットーに、誰でも実践できるBashスクリプトの書き方を発信しています。

このサイトでは、Bashの基礎から実践的なスクリプト作成まで、初心者でもわかりやすく解説しています。少しでも「Bashって便利だな」と思ってもらえたら嬉しいです!

# 好きなこと
- シンプルなコードを書くこと
- コマンドラインを快適にカスタマイズすること
- 自動化で時間を生み出すこと

# このサイトを読んでほしい人
- Bashに興味があるけど、何から始めればいいかわからない人
- 定型業務を自動化したい人
- 効率よくターミナルを使いこなしたい人

Bashの世界に一歩踏み出して、一緒に「Bash道」を極めていきましょう!

Bash玄をフォローする