systemctl と journalctl を使った Linux サービスのトラブルシューティング
systemctl と journalctl を使用して、失敗した、または異常な Linux サービスをデバッグするための実践的なワークフロー。
systemctl と journalctl を使った Linux サービスのトラブルシューティング
Linux サービスが失敗した場合、最速の解決策は通常ウェブ検索ではありません。それは、3 つのローカルチェックです: systemd が何が起こったと考えているか、サービスが何をログに記録したか、そして障害の前に何が変更されたか。systemctl と journalctl は、推測することなくこれらの答えを提供します。
このガイドでは、一般的なサービス障害を例として使用します: 起動しないサービス、実行中だが有用な作業を行っていないプロセス、正常に見えた後に終了するサービス。これらのコマンドは、ほとんどの systemd 管理サービスに適用されますが、正確なユニット名とログの場所は、ディストリビューションとパッケージによって異なります。
systemctl と journalctl を理解する
トラブルシューティングに入る前に、これら 2 つの主要なツールの役割を理解することが重要です:
systemctl: このコマンドは、systemdシステムおよびサービス マネージャーを制御および照会するための中心的なユーティリティです。サービスの開始、停止、再起動、ステータスの確認、有効化/無効化を行うことができます。journalctl: このコマンドは、systemd ジャーナルを照会するために使用されます。これは、一元化されたログ システムです。カーネル、システム サービス、およびアプリケーションからログを収集し、システム イベントの統一されたビューを提供します。journalctlは、サービスが失敗したり、予期しない動作をした 理由 を理解するために非常に役立ちます。
一般的なトラブルシューティングのシナリオと解決策
典型的な問題とその対処法を見てみましょう:
1. サービスの起動に失敗した
これはおそらく最も一般的な問題です。サービスを起動しようとすると、すぐに失敗します。
ステップ 1: サービスのステータスを確認する
systemctl status を使用して、サービスの状態と最近のログ エントリの概要を即座に取得します。
sudo systemctl status apache2.service
期待される出力 (例示 - 実際の出力は異なる場合があります):
● apache2.service - The Apache HTTP Server
Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
Active: **failed** (result: exit-code) since Tue 2023-10-27 10:00:00 UTC; 1min ago
Docs: https://httpd.apache.org/docs/2.4/
Process: 12345 ExecStart=/usr/sbin/apachectl start (code=exited, status=1/FAILURE)
Main PID: 12345 (code=exited, status=1/FAILURE)
Oct 27 10:00:00 your-server systemd[1]: Starting The Apache HTTP Server...
Oct 27 10:00:00 your-server apachectl[12345]: AH00526: Syntax error on line 123 of /etc/apache2/apache2.conf:
Oct 27 10:00:00 your-server apachectl[12345]: Invalid Mutex directory in argument file: '/var/run/apache2/'
Oct 27 10:00:00 your-server systemd[1]: apache2.service: Main process exited, code=exited, status=1/FAILURE
Oct 27 10:00:00 your-server systemd[1]: **Failed** to start The Apache HTTP Server.
Oct 27 10:00:00 your-server systemd[1]: apache2.service: Unit entered failed state.
分析: systemctl status の出力は、Active: failed を明確に示し、エラー メッセージの一部を提供します: Invalid Mutex directory in argument file: '/var/run/apache2/'。これは設定の問題を示唆しています。
ステップ 2: journalctl でログを調査する
より詳細な情報を得るには、journalctl を使用して、失敗したサービスに固有のログを表示します。-u フラグはユニット (サービス) を指定します。
sudo journalctl -u apache2.service -xe
-u apache2.service:apache2.serviceユニットのログをフィルタリングします。-x: 一部のログ メッセージに説明を追加します。-e: ジャーナルの最後にジャンプし、最新のエントリを表示します。
潜在的な発見: journalctl の出力は、設定エラー、権限の問題、または依存関係の問題に関するより多くのコンテキストを明らかにする可能性があります。
ステップ 3: 設定ファイルを確認する
エラー メッセージに基づいて、関連する設定ファイルを調べます。上記の例では、/etc/apache2/apache2.conf とディレクトリ /var/run/apache2/ を指しています。
sudo nano /etc/apache2/apache2.conf
解決策: このような問題は、多くの場合、ランタイム ディレクトリの欠落、パッケージの変更、または存在しなくなったパスを参照する設定ファイルが原因で発生します。インターネット上の例から盲目的にディレクトリを作成しないでください。まず、アプリケーションがディストリビューションで何を期待しているかを確認し、次に欠落しているパスまたは設定を修正します。考えられる修復は次のようになります:
sudo mkdir -p /var/run/apache2/
sudo chown www-data:www-data /var/run/apache2/
sudo systemctl start apache2.service
エラーが構文の問題を示している場合は、再起動する前にアプリケーション独自の設定テストを実行します:
sudo apachectl configtest
sudo nginx -t
sudo sshd -t
アプリケーション固有のバリデーターは、systemd が理解できない間違いをキャッチします。Systemd はプロセスが終了したかどうかを認識します。Nginx の server ブロックが間違った証明書ファイルを指しているかどうか、Apache ディレクティブが別のコンテキストに属しているかどうかは認識しません。
2. サービスは実行中だが応答しない
systemctl status がサービスを active (running) と表示することがありますが、意図された機能を実行していません (例: Web サーバーがページを提供していない)。
ステップ 1: サービスのステータスと PID を確認する
実際に実行中であり、プロセス ID (PID) があることを確認します。
sudo systemctl status nginx.service
active (running) と表示された場合は、PID をメモします。
ステップ 2: エラーのサービス ログを調べる
実行中であっても、サービスは正しく機能するのを妨げる内部エラーに遭遇している可能性があります。
sudo journalctl -u nginx.service -f
-f: ログ出力をリアルタイムで追跡します。これは、journalctlの実行中に問題をトリガーできる場合 (例: Web ページにアクセスしようとする) に便利です。
ステップ 3: アプリケーション固有のログを確認する
多くのサービスは、systemd のジャーナルに加えて、独自のログを書き込みます。Nginx や Apache などの Web サーバーの場合は、通常のログの場所 (例: /var/log/nginx/error.log、/var/log/apache2/error.log) を確認します。
sudo tail -n 50 /var/log/nginx/error.log
ステップ 4: リソース使用率を確認する
過負荷のシステムは、サービスが応答しなくなる原因となる可能性があります。
top
htop
free -h
サービスのプロセスによる高い CPU、メモリ、またはディスク I/O を探します。
また、サービスが期待どおりの場所でリッスンしているかどうかを確認します:
sudo ss -ltnp
sudo ss -lunp
Web サービスの場合、systemctl で nginx がアクティブであることを確認することは、話の半分にすぎません。0.0.0.0:80、127.0.0.1:8080、IPv6 ソケット、またはソケットなしのいずれにバインドされているかを知る必要があります。ファイアウォール ルール、リバース プロキシの不一致、または不正なバインド アドレスにより、正常なプロセスが外部から壊れているように見える可能性があります。
解決策: ログが問題を示している場合、またはリソースがひっ迫している場合は、次のことが必要になる場合があります:
- 設定を最適化します。
- サービスを再起動します (
sudo systemctl restart <service_name>.service)。 - 基盤となるシステム リソースの問題を調査します。
- 必要に応じてシステム リソースを増やします。
3. サービスが予期せず停止する
以前は実行されていたサービスが突然停止した場合、多くの場合、ハンドルされていない例外またはウォッチドッグ タイムアウトが原因です。
ステップ 1: journalctl で最近の履歴を確認する
journalctl を使用して、サービスが停止する直前に何が起こったかを確認します。おおよその時間がわかっている場合は、--since および --until フラグが役立ちます。
sudo journalctl -u <service_name>.service --since "1 hour ago"
または、最後の起動以降のサービスに関連するすべてのログを表示するには:
sudo journalctl -u <service_name>.service -b
ステップ 2: コア ダンプまたはクラッシュ レポートを探す
サービスがクラッシュした場合、システムがコア ダンプまたはクラッシュ レポートを生成した可能性があります。
ls -l /var/crash/
ステップ 3: systemd サービス ユニット ファイルを確認する
Restart= ディレクティブと WatchdogSec= 設定について、サービスのユニット ファイル (通常は /etc/systemd/system/ または /lib/systemd/system/ にある) を調べます。正しくない Restart= 設定や短すぎる WatchdogSec= は、予期しない再起動や障害を引き起こす可能性があります。
systemctl cat <service_name>.service
解決策: ログで特定された根本的な原因に対処します。これには、コードのバグの修正、systemd ユニット ファイル パラメーターの調整、またはリソース制限の増加が含まれる場合があります。
再起動が繰り返される場合は、systemd がユニットをレート制限していないか確認します:
systemctl status <service_name>.service
journalctl -u <service_name>.service --since "30 minutes ago"
Start request repeated too quickly に関するメッセージは、通常、サービスが短時間に複数回クラッシュしたことを意味します。根本的な問題を修正した後、失敗した状態をクリアします:
sudo systemctl reset-failed <service_name>.service
sudo systemctl start <service_name>.service
4. systemctl enable または systemctl disable の問題
実行時の障害ではありませんが、サービスの有効化または無効化に関する問題が発生する可能性があります。
問題: サービスが有効になっているが、起動時に開始されない、またはその逆。
ステータスを確認する:
sudo systemctl is-enabled <service_name>.service
このコマンドは、enabled または disabled を出力します。
トラブルシューティング:
- サービス ユニット ファイル自体が有効で、正しく配置されていることを確認します (例:
/etc/systemd/system/)。 - ユニット ファイルに変更を加えた後は、必ず
sudo systemctl daemon-reloadを実行します。 - 有効になっていても、起動エラーが原因でサービスがアクティブにならない可能性があるため、サービスのログ (
journalctl -u <service_name>.service) を確認します。
効果的なトラブルシューティングのためのヒント
systemctl statusから始める: 常にここから始めてください。クイック スナップショットを提供し、多くの場合、正しい方向を示します。journalctl -u <service>を使用する: これは、なぜ 何かが起こっているのかを理解するための主要なツールです。journalctlの-fフラグ: 問題を再現しようとするときのリアルタイム監視に非常に役立ちます。systemctl restart <service>: 設定を変更した後は、常にサービスを再起動して適用します。systemctl daemon-reload:.serviceユニット ファイルを変更した後は重要です。- 依存関係を確認する: サービスが依存するサービスが起動していないか、それ自体が失敗しているために、サービスが失敗することがあります。
systemctl statusはこれを示すことがよくあります。 - 権限: 多くのサービス障害は、ファイルまたはディレクトリの権限が正しくないことが原因です。サービスが実行されるユーザーが必要なアクセス権を持っていることを確認します。
- ネットワークの問題: サービスがネットワークに依存している場合は、ネットワーク接続、ファイアウォール ルール、およびポートの可用性を確認します。
有効なトラブルシューティングの順序
プレッシャーがかかっているときは、毎回同じ順序を使用します:
systemctl status <service>.service
journalctl -u <service>.service -b --no-pager
systemctl cat <service>.service
systemctl list-dependencies <service>.service
現在の状態から始め、次に現在の起動からのログを読み、次に systemd が認識するユニットをそのまま検査し、最後に依存関係を確認します。サービスがネットワークに面している場合は、ss -ltnp とローカルの curl またはクライアント テストを追加します。設定ファイルを読み取る場合は、サービス独自の設定バリデーターを実行します。
重要なのは、ランダムな再起動を避けることです。再起動は、設定変更後やプロセスがスタックした後の有効な修正になる可能性がありますが、証拠も破壊します。何を変更しているのか、なぜ変更しているのかを理解できるように、最初にジャーナルを十分に読んでください。
迷子にならずにジャーナル出力を読む
journalctl は、特にビジーなサーバーではノイズが多くなる可能性があります。狭い範囲から始めて、必要な場合にのみ広げてください。
現在の起動の 1 つのサービスの場合:
journalctl -u <service>.service -b --no-pager
過去数分間の場合:
journalctl -u <service>.service --since "15 minutes ago" --no-pager
前回の起動の場合:
journalctl -u <service>.service -b -1 --no-pager
この前回の起動ビューは、サービスが起動中に失敗してから回復した場合、または調査する前にマシン全体が再起動された場合に役立ちます。起動を一覧表示するには:
journalctl --list-boots
サービスが構造化フィールドまたは長い行をログに記録する場合は、短い ISO タイムスタンプを使用します:
journalctl -u <service>.service -o short-iso --no-pager
ログを共有する必要がある場合は、シークレット、トークン、内部ホスト名、および顧客データを削除します。サービス ログには、環境から派生した設定、URL、ヘッダー、または接続文字列が含まれることがよくあります。クリーンなトラブルシューティングの習慣には、出力をどこかに貼り付ける前に編集することが含まれます。
systemctl が「Active」と表示しても、ユーザーが依然として障害を認識する場合
active (running) 状態は、systemd がユニットの期待に一致するプロセスを持っていることのみを意味します。アプリケーションが正常であることを証明するものではありません。Web アプリケーションは実行中でも HTTP 500 を返す可能性があります。ワーカーはアクティブでも、不良なキュー メッセージでスタックする可能性があります。データベース プロキシは実行中でも、すべてのバックエンド接続が失敗する可能性があります。
ネットワーク サービスの場合は、ユーザーが依存しているのと同じレイヤーからテストします:
curl -v http://127.0.0.1:8080/health
curl -v http://localhost/health
curl -v https://service.example.com/health
これら 3 つのチェックは、異なる質問に答えます。最初のチェックはローカル アプリ ポートを確認します。2 番目のチェックにはローカル リバース プロキシが含まれる場合があります。3 番目のチェックは、DNS、TLS、ルーティング、ファイアウォール ルール、および公開パスを確認します。
ワーカー サービスの場合は、それらが消費または生成するものを確認します。キュー ワーカーには、キューの深さチェックが必要な場合があります。バックアップ サービスには、最近の出力ファイルが必要な場合があります。メトリクス コレクターには、メトリクス バックエンドに対するクエリが必要な場合があります。systemctl は、監視が機能しているかどうかを示します。アプリケーション チェックは、サービスが有用かどうかを示します。
一度に 1 つの変数を修正する
デプロイ後にユニットが失敗した場合、複数のことを変更して再起動したくなります。これにより、本当の原因が隠れる可能性があります。一度に 1 つの変更を優先します:
systemctl cat my-app.service
journalctl -u my-app.service --since "30 minutes ago" --no-pager
sudo systemctl edit my-app.service
sudo systemctl daemon-reload
sudo systemctl restart my-app.service
次に、次のことを変更する前に結果を確認します。障害がファイルの欠落である場合は、ファイル パスを修正します。権限エラーの場合は、所有権またはモードを修正します。依存関係の場合は、ユニットの関係またはアプリケーションの再試行動作を修正します。遅くて退屈なトラブルシューティングは、5 つの追跡されていない編集による再起動ループよりも高速であることがよくあります。