サービスが起動しない・落ちるとき
systemdサービスが起動に失敗したり、動いていたはずが落ちていたりするときは、systemctl status で状態と直近ログを見るのが最初の一手です。journalctl -u で過去にさかのぼり、exit codeやRestart設定によるループの有無を確認します。設定ミス・ポート衝突・権限・依存先落ちという4大原因を押さえれば、原因の見当が速く付きます。
「systemctl start で起動したはずのサービスが、いつの間にか止まっている」「デプロイ後、アプリにアクセスできない」――systemd管理下のサービスにまつわる障害は、運用でもっとも頻繁に出会う種類の1つだ。
幸い、systemdはサービスの状態や直近のログを1コマンドで教えてくれる。落ち着いて手順を踏めば、原因の見当は驚くほど速く付く。
🩺 まず systemctl status で聞診する
最初の一手は systemctl status サービス名 だ。医者が聴診器を当てるように、サービスの今の状態をひと目で確認できる。
表示される情報は多いが、着目すべきは主に3つ。Active 行の状態、Main PID の有無、そして下部に表示される直近ログの内容だ。failed になっていれば起動に失敗しており、その理由の断片がログ欄に出ていることが多い。
📜 journalctl -u -e で過去へさかのぼる
status に出るログは直近の数行だけなので、経緯を追うにはもっと過去までさかのぼりたい。そこで使うのが journalctl -u サービス名 -e だ。
これで「いつから調子が悪くなったか」「再起動を何度も試みているか」「特定のエラーが繰り返し出ていないか」を時系列で追える。--since '1 hour ago' のように時間を指定して絞り込むのも有効だ。
🔢 exit codeとRestart=によるループ
ログの中には exit code(終了コード)が記録されている。これはプロセスが「なぜ終了したか」を表す数値で、0なら正常終了、それ以外は何らかの異常を意味する。
systemctl status の出力にも Main PID の行の近くに「(code=exited, status=1/FAILURE)」のように exit code が表示される。数値そのものの意味はアプリごとに異なるが、「0か非0か」だけでも起動失敗の事実を機械的に確認できる。
systemdのユニット設定には Restart= という項目があり、on-failure などに設定されていると、サービスが落ちるたびに自動で再起動を試みる。これは可用性を高める良い機能だが、原因が解消していないと「起動→即失敗→再起動→即失敗」を延々と繰り返す再起動ループに陥る。
🧯 4大原因を型として押さえる
exit codeやログの内容が読めたら、原因を絞り込む。サービス起動失敗の原因は、実務上ほぼ次の4パターンに集約される。
1つ目は設定ミスだ。設定ファイルの構文エラーが典型で、多くのミドルウェアには構文だけをチェックする機能が用意されている。nginxなら nginx -t、Apacheなら apachectl configtest のように、実際に再起動する前に構文の妥当性だけを確認できる。
2つ目はポート衝突だ。すでに別のプロセスが同じポートを使っていると、後から起動しようとしたサービスは待ち受けに失敗する。先ほどのSVGの例のように bind() failed と出ていたら、まずこれを疑う。ss -tlnp や lsof -i :ポート番号 で、そのポートをすでに誰が使っているかを確認できる。
3つ目は権限だ。設定ファイルや証明書、ソケットファイルなどにサービス実行ユーザーがアクセスできる権限がないと、起動時にPermission deniedで失敗する。ファイルの所有者・パーミッションを確認する。
4つ目は依存先落ちだ。データベースに接続できないと起動しないアプリのように、そのサービスが依存する別のサービスやリソースが先に落ちていることがある。systemdのユニット定義には依存関係(After=やRequires=)を書けるが、依存先自体が正常に動いているかは別途確認が必要になる。
💾 restartの前に、ログを保存する習慣
原因調査の途中で systemctl restart を実行すると、それまでの状態を示す直近ログが上書きされてしまい、貴重な手がかりを失うことがある。
systemctl status で状態を掴み、journalctl -u -e で経緯を追い、exit codeとRestart=の動きを読み、4大原因に当てはめる――この流れを型として持っておくと、深夜のアラートにも落ち着いて対応できるようになる。