本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
netstat/ssコマンドによるネットワーク診断
DevOpsエンジニアとして、アプリケーションのパフォーマンス問題や接続障害が発生した際、迅速なネットワーク診断は不可欠です。本稿では、Linuxにおけるnetstatおよびssコマンドを用いた診断手法を、安全なBashスクリプト、jq、curl、そしてsystemdによる自動化と組み合わせて解説します。
要件と前提
要件
netstat/ssコマンドによるネットワーク接続状態の確認とトラブルシューティング。bashスクリプトはset -euo pipefail、trap、安全な一時ディレクトリ (mktemp -d) を用いたidempotentかつ安全な書き方を遵守。jqによるJSON処理、curlによるTLS/再試行/バックオフの例示。systemd unit/timerによる診断の自動化。mermaidフローチャートによる診断プロセスの可視化。root権限の扱いと権限分離への言及。
前提
Linux環境(Ubuntu/CentOSなど)が利用可能であること。
bash、ss(iproute2パッケージに含まれる)、jq、curl、systemdがインストール済みであること。
実装
ネットワーク診断スクリプト (diagnose_network.sh)
以下のスクリプトは、ssコマンドでネットワーク接続情報を取得し、curlで特定のAPIエンドポイントへの疎通確認を行います。取得したJSONデータはjqで処理されます。
#!/usr/bin/env bash
set -euo pipefail
# 安全な一時ディレクトリの作成と自動クリーンアップ
readonly TMPDIR=$(mktemp -d -t network-diag-XXXXXX)
function cleanup {
echo "--- INFO: Cleaning up temporary directory ${TMPDIR} ---"
rm -rf "${TMPDIR}"
}
trap cleanup EXIT # スクリプト終了時にcleanup関数を実行
echo "--- $(date '+%Y-%m-%d %H:%M:%S') --- ネットワーク接続診断開始 ---"
# 1. ssコマンドによるネットワーク接続状態の確認
# -t: TCPソケット, -u: UDPソケット, -n: ホスト名/ポート番号を解決しない, -a: 全てのソケットを表示, -p: プロセス情報を表示
# 注意: '-p' オプションは、通常root権限(またはCAP_NET_ADMIN)が必要です。
# 一般ユーザーで実行する場合は、'-p' を外すか、sudoersで適切な権限を付与してください。
echo "### TCP/UDPのLISTENおよびESTABLISHED状態の接続を表示 (プロセス情報付き、要root権限の場合あり) ###"
if ss -tunap > "${TMPDIR}/ss_output.txt" 2>&1; then
cat "${TMPDIR}/ss_output.txt"
echo
echo "--- 特定ポート(例: 22 SSH)の接続状況 ---"
if grep -E ':(22|ssh)' "${TMPDIR}/ss_output.txt" | head -n 1 >/dev/null; then
grep -E ':(22|ssh)' "${TMPDIR}/ss_output.txt"
else
echo "ポート 22 (SSH) の接続は見つかりませんでした。"
fi
else
echo "ERROR: ssコマンドの実行に失敗しました。権限やインストール状況を確認してください。" >&2
cat "${TMPDIR}/ss_output.txt" >&2 # ssのエラー出力を表示
exit 1
fi
echo
# 2. curlコマンドによるAPI疎通確認 (TLS/再試行/バックオフ)
readonly API_ENDPOINT="https://jsonplaceholder.typicode.com/todos/1" # テスト用公開API
readonly MAX_RETRIES=3
readonly RETRY_DELAY=5 # 秒
readonly TOTAL_RETRY_TIME=$((MAX_RETRIES * RETRY_DELAY * 2)) # 最大リトライ時間
echo "### API疎通確認: ${API_ENDPOINT} (最大${MAX_RETRIES}回リトライ) ###"
if curl -sS --fail-with-body \
--retry "${MAX_RETRIES}" \
--retry-delay "${RETRY_DELAY}" \
--retry-max-time "${TOTAL_RETRY_TIME}" \
--output "${TMPDIR}/api_response.json" \
"${API_ENDPOINT}"; then
echo "API接続成功。"
# 3. jqによるJSONデータの処理
echo "--- 取得したJSONデータの一部をjqで処理 ---"
if jq '.title' "${TMPDIR}/api_response.json" > /dev/stdout; then
echo "JSON処理成功。"
else
echo "ERROR: jqによるJSON処理に失敗しました。" >&2
cat "${TMPDIR}/api_response.json" >&2 # 取得したJSONを表示
exit 1
fi
else
echo "ERROR: API接続に失敗しました: ${API_ENDPOINT}" >&2
if [[ -f "${TMPDIR}/api_response.json" ]]; then
echo "--- エラーレスポンス ---" >&2
cat "${TMPDIR}/api_response.json" >&2
fi
exit 1
fi
echo "--- ネットワーク接続診断完了 ---"
exit 0
root権限の扱いと権限分離
ss -pオプション: プロセスID (PID) やプロセス名を詳細に表示するには、通常root権限が必要です。一般ユーザーで実行すると情報が制限されるか、エラーになる場合があります。最小権限の原則: 診断スクリプトは、必要な情報に応じて
sudoを使用するか、CAP_NET_ADMINなどのLinux Capabilitiesをプロセスに付与することを検討してください。systemdのUser/Group: 後述のsystemdユニットではUser=およびGroup=オプションで実行ユーザーを指定し、不必要なroot権限での実行を避けることができます。この場合、ss -pのような特権操作はできません。
検証
上記スクリプトをdiagnose_network.shとして保存し、実行権限を与えます。
chmod +x diagnose_network.sh # root権限が必要なss -pを含む場合 sudo ./diagnose_network.sh # 一般ユーザーで実行する場合 (ss -pの情報は制限されるか表示されない) ./diagnose_network.sh
ssコマンドの出力: LISTEN、ESTABLISHED、TIME_WAITなどの状態や、ローカル/リモートのアドレス・ポート、およびプロセス情報(root権限時)が正しく表示されることを確認します。curlの出力: API接続が成功し、HTTPステータスコード200が返されること、およびリトライメカニズムが機能すること(ネットワーク一時障害を模擬するなど)を確認します。jqの出力: 取得したJSONデータから.titleフィールドが正しく抽出されることを確認します。
運用
systemdによる自動化
診断スクリプトを定期的に実行し、ログを収集するためにsystemdのserviceとtimerユニットを定義します。
1. スクリプトの配置
スクリプトを/usr/local/bin/diagnose_network.shに配置します。
(ここではss -pは一般ユーザーでは機能しないことを前提に、権限分離を優先しUser=someuserを設定します。必要であればスクリプトから-pオプションを削除してください。)
sudo install -m 755 diagnose_network.sh /usr/local/bin/
2. systemd serviceユニットの作成 (/etc/systemd/system/network-diag.service)
[Unit] Description=Automated Network Connection Diagnostic Documentation=https://example.com/network-diag-service After=network.target [Service] Type=oneshot # 診断スクリプトを特定の一般ユーザー/グループで実行 # 必要に応じて、専用ユーザー (例: networkdiag) を作成し、ここに指定 User=nobody Group=nogroup ExecStart=/usr/local/bin/diagnose_network.sh # StandardOutput, StandardError はデフォルトでjournaldに送られる StandardOutput=journal StandardError=journal # 失敗時にアラートなど、後続の処理を追加可能 (例: OnFailure=alert-script.service) [Install] WantedBy=multi-user.target
3. systemd timerユニットの作成 (/etc/systemd/system/network-diag.timer)
[Unit] Description=Run network connection diagnostic every 5 minutes [Timer] # システム起動後1分後に最初の実行 OnBootSec=1min # サービスがアクティブになった5分後に再度実行 (定期的実行) OnUnitActiveSec=5min # 同時実行を避けるためのランダムな遅延 RandomSec=30s [Install] WantedBy=timers.target
4. systemdユニットの有効化と起動
sudo systemctl daemon-reload sudo systemctl enable --now network-diag.timer
5. ログの確認
systemctl status network-diag.timer systemctl status network-diag.service journalctl -u network-diag.service --no-pager
トラブルシュート
| 問題点 | 診断方法 |
|---|---|
| 接続が見えない | – ss -tunap: プロセスが表示されない場合、サービスが停止しているか、異なるユーザーで実行されている可能性がある。 -lでLISTENポートも確認。– ファイアウォール: sudo iptables -Lやsudo ufw statusでブロックされていないか確認。– ルーティング: ip rでルーティングテーブルを確認。 |
TIME_WAITが多い |
サーバー側で大量のCLOSE_WAIT接続がある場合、アプリケーションがソケットを適切に閉じずに放置している可能性がある。クライアント側でTIME_WAITが多いのは正常な挙動。 |
CLOSE_WAITが多い |
サーバー側でアプリケーションがソケットのクローズを処理していない可能性。アプリケーションログを確認し、リソースリークやデッドロックを疑う。 |
curlが失敗する |
– HTTPステータスコード: --fail-with-bodyでエラーレスポンスを確認。HTTP 4xx/5xxはアプリケーション側の問題、ネットワークの問題はcurlのエラーコードで。 – curlエラーコード: man curl-errorsで詳細を確認。例:6 (Couldn’t resolve host), 7 (Couldn’t connect to host), 35 (SSL connect error)。– TLS/SSL: --verbose (-v) オプションで詳細なTLSハンドシェイクのログを確認。証明書の問題 (--cacert, --insecure) も考慮する。 |
systemdが動かない |
– systemctl status <unit>: サービスの状態とエラーメッセージを確認。– journalctl -u <unit>: サービスの詳細なログを確認。– スクリプトの実行権限: ExecStartで指定されたスクリプトに実行権限があるか確認 (chmod +x)。– User/Group: 指定したユーザーが存在し、スクリプト実行に必要な権限を持っているか確認。 |
ネットワーク診断フロー
graph TD
A["システム/アプリ異常検知"] --> B{"定期監視 (systemd Timer) 発火?"};
B --|はい| C["診断Service実行"];
B --|いいえ| D["手動診断開始"];
C --> E["診断スクリプト実行"];
D --> E;
E --> F["ssコマンド実行"];
F --> G["curlコマンド実行"];
G --> H["jqで結果解析"];
H --|エラー検出?| I{"はい"};
H --|エラー検出?| J{"いいえ"};
I --> K["診断結果ログ出力"];
K --> L["アラート発報"];
L --> M["担当者による詳細調査"];
J --> K;
K --> N["次サイクル待機"];
M --> O["問題解決/サービス復旧"];
O --> N;
まとめ
netstatとその後継であるssコマンドは、Linuxシステムにおけるネットワーク診断の基礎ツールです。特にssは高速かつ詳細な情報を提供します。本稿では、これらのコマンドを核に、安全なBashスクリプトの書き方、jqによるデータ解析、curlによる外部サービス疎通確認、そしてsystemdを用いた自動監視の仕組みをDevOpsエンジニアの視点から解説しました。これらの技術を組み合わせることで、システムのネットワーク状態を常に把握し、問題発生時の迅速なトラブルシューティングと安定したサービス運用に貢献できます。権限分離と最小権限の原則を忘れずに、セキュアな運用を心がけましょう。

コメント