Linux管理・運用の基本
システム管理者のための実践ガイド
システム管理者のための実践ガイド
深夜にサービス停止を検知して慌てて復旧、週末のメンテナンス作業に追われる...そんな運用上のトラブルや手間を自動化で未然に防ぐためのスクリプト活用術を紹介します。本記事では、Linuxの日常的な運用タスクを自動化するための実践的なシェルスクリプトの例を、具体的なコードとともに詳しく解説します。
シェルスクリプトは、コマンドを組み合わせて一連の処理を自動実行させるためのプログラムです。運用スクリプトを作成する際は、以下のポイントを意識すると良いでしょう。
サービスのログを監視し、特定のエラー文字列(例: ERROR
、FATAL
)を検出したらSlackやメールで通知するスクリプトを作成してみましょう。
monitor_log.sh
#!/bin/bash
# 予期せぬエラーで停止するのを防ぐため、安全設定を記述
set -euo pipefail
IFS=$'\n\t'
LOG_FILE="/var/log/my_app.log"
TARGET_STRING="ERROR|FATAL"
WEBHOOK_URL="https://hooks.slack.com/services/..."
NOTIFICATION_MESSAGE="重大なエラーが検出されました!"
# 新規エラー行を抽出する(grepに一致がない場合でもスクリプトが停止しないようpipefailを回避)
while IFS= read -r line; do
# 本文の生成は printf を推奨(可搬性/安全性のため)
MESSAGE_BODY=$(printf "%s\n\nログ内容:\n\`\`\`\n%s\n\`\`\`" \
"$NOTIFICATION_MESSAGE" "$line")
# jqを使ってJSONペイロードを安全に組み立てる
payload=$(/usr/bin/jq -n --arg text "$MESSAGE_BODY" '{text: $text}')
# curlの--fail-with-bodyオプションが使えるか確認
CURL_OPTS="--fail-with-body"
if ! /usr/bin/curl --help all 2>/dev/null | /usr/bin/grep -q -- '--fail-with-body'; then
CURL_OPTS="--fail"
fi
# Slackに通知を送信。-sS --fail-with-body で失敗時のみエラーを出す
/usr/bin/curl -sS "$CURL_OPTS" \
-H 'Content-Type: application/json' \
-d "$payload" \
"$WEBHOOK_URL"
done < <(/usr/bin/tail -n 100 "$LOG_FILE" | /usr/bin/grep -E "$TARGET_STRING")
tail -n 100 "$LOG_FILE"
: 最新の100行を読み込みます。これにより、ログファイル全体をスキャンする負荷を減らします。grep -E "$TARGET_STRING"
: 複数のエラー文字列をOR条件で検索します。|
で区切って複数の文字列を指定できます。/usr/bin/curl
: SlackのIncoming WebhookなどのAPIを利用して、指定されたURLにメッセージを送信します。cron
で実行する場合、curl
のようにパスが通っていない可能性があるため、/usr/bin/curl
のようにフルパスでコマンドを記述すると安全です。mail
コマンドを使えばメールでの通知も可能です。echo "メッセージ" | mail -s "件名" admin@example.com
のように応用できます。Webサーバーやデータベースなどの重要なサービスが何らかの理由で停止してしまった場合に、自動的に再起動を試みるスクリプトです。
restart_service.sh
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
# 複数のサービスを配列で定義
SERVICES=("httpd" "mysqld")
LOG_FILE="/var/log/restart_service.log"
for SERVICE_NAME in "${SERVICES[@]}"; do
# systemctlが利用可能か確認
if ! command -v systemctl >/dev/null 2>&1; then
echo "systemctlコマンドが見つかりません。スクリプトを終了します。"
# Docker環境では 'docker restart'、古いLinuxでは 'service' など、
# 環境に合わせてコマンドを変更してください。
exit 1
fi
if ! /usr/bin/systemctl is-active --quiet "$SERVICE_NAME"; then
# タイムスタンプを可読性の高い形式で出力
echo "$(/bin/date '+%F %T'): $SERVICE_NAME is not running. Attempting to restart." | /usr/bin/tee -a "$LOG_FILE"
# サービスの再起動にはroot権限が必要
/usr/bin/systemctl restart "$SERVICE_NAME"
# 再起動後、ステータスを確認
if /usr/bin/systemctl is-active --quiet "$SERVICE_NAME"; then
echo "$(/bin/date '+%F %T'): $SERVICE_NAME restarted successfully." | /usr/bin/tee -a "$LOG_FILE"
else
echo "$(/bin/date '+%F %T'): Failed to restart $SERVICE_NAME. Manual intervention required." | /usr/bin/tee -a "$LOG_FILE"
# ここに管理者への通知コマンドを追加
fi
fi
done
systemctl is-active --quiet "$SERVICE_NAME"
: 指定したサービスが稼働中かどうかを確認します。--quiet
オプションを付けると、標準出力に何も出力せず、終了コード(成功: 0、失敗: 1)のみを返します。if ! ...; then ... fi
: !
は論理NOTを表し、サービスが稼働中でない場合に条件が真となります。tee -a "$LOG_FILE"
: echo
の内容を標準出力に表示すると同時に、指定したログファイルに追記します。cron
と組み合わせて数分おきに実行することで、サービスの自動リカバリを実現できます。スクリプトの実行にはroot権限が必要になる点に注意しましょう。ディスク容量の肥大化を防ぐために、古いログファイルや一時ファイルを自動的に削除するスクリプトです。
cleanup_old_files.sh
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
# 7日以上前のファイルを削除
TARGET_DIR="/path/to/logs"
/usr/bin/find "$TARGET_DIR" -type f -name "*.log" -mtime +7 -delete
# 30日以上前のバックアップファイルを削除
BACKUP_DIR="/path/to/backups"
/usr/bin/find "$BACKUP_DIR" -type f -name "*.tar.gz" -mtime +30 -delete
# ディスク使用量をレポート
# df -hはマウントポイントを、du -shはディレクトリ自体のサイズを表示します
echo "--- ディレクトリのディスク使用量 ---"
/usr/bin/du -sh "$TARGET_DIR"
echo "--- ファイルシステムのディスク使用量 ---"
/usr/bin/df -h "$TARGET_DIR"
/usr/bin/find
: 指定した条件に合うファイルを検索するコマンドです。-type f
: 検索対象をファイルに限定します。-name "*.log"
: ファイル名を指定します。*
を使用することで、特定のファイルパターンに合致するファイルを対象にできます。-mtime +7
: 最終更新時刻が7日以上前のファイルを指定します。-delete
: GNU find
の拡張機能で、検索で見つかったファイルを削除します。-exec rm {} \;
よりも高速で安全です。du -sh
: 指定したディレクトリのディスク使用量を表示します。df -h
: 指定したディレクトリが含まれるファイルシステム全体のディスク使用量を表示します。【重要】スクリプト実行前の注意点 ファイル削除を伴うスクリプトは、誤って重要なファイルを消してしまうリスクがあります。初めて実行する際は、必ずドライラン(dry-run)で何が削除されるか確認しましょう。
# 実行前の確認(dry-run推奨!)
/usr/bin/find "$TARGET_DIR" -type f -name "*.log" -mtime +7 -print
また、logrotate
を利用している環境では、ログファイル名が予期せず変わることがあるため、find
の条件設定には注意が必要です。
作成したスクリプトファイルは、実行できるように権限を付与する必要があります。
$ chmod +x monitor_log.sh
このコマンドを実行することで、スクリプトが実行可能になります。
作成したスクリプトは、cron
(クーロン)というLinuxの定期実行ツールを使って自動化できます。
crontabへの登録例
# ターミナルで以下を実行
$ crontab -e
エディタが開いたら、以下のような行を追加して保存します。
# 毎分、ログ監視スクリプトを実行
* * * * * /path/to/monitor_log.sh
# 毎日AM3:00、定期メンテナンススクリプトを実行
0 3 * * * /path/to/cleanup_old_files.sh
この設定により、手動でコマンドを実行する手間がなくなります。
本記事では、Linuxサーバーの管理・運用を効率化するための実践的なシェルスクリプトの例を3つご紹介しました。これらのスクリプトをベースに、監視対象や通知方法、削除条件などをカスタマイズすることで、あなたの環境に合わせた自動化を進めることができます。
小さな作業の自動化から始めることで、徐々に運用の安心感と自由な時間を増やすことができます。
この記事がシェルスクリプトについて理解を深める一助となれば幸いです。次回は、より高度なセキュリティ運用に欠かせないSELinux/AppArmorについて掘り下げていきます。
ご覧いただきありがとうございました。