【実践シェルスクリプト講座 第1回】サーバーが止まる前に!「ディスク容量監視」と「ログ自動整理」の鉄則
こんにちは!「リナックス先生」です。
前回までの「Bash講座」では、コマンドの基本や変数の使い方といった基礎体力をつけてきましたね。
コウ君、その後サーバーの管理はどう?順調にいじれてる?
先生…実は昨日、テスト環境のサーバーがいきなり動かなくなってしまったんです。
再起動してもダメで、エラーログを見ようとしたら「No space left on device」って出て…。
結局、溜まりに溜まったログファイルがディスクを埋め尽くしていたのが原因でした。
あらら、典型的な「ディスクフル」障害ね。
でも、それは誰もが通る道よ。大事なのは「同じ失敗を繰り返さないこと」。
今回からは新シリーズ「実践シェルスクリプト講座」として、現場で本当に使える自動化スクリプトを作っていくわよ!
基礎編を卒業したあなたに贈る、より実務的なスクリプト作成ガイド。
第1回は、サーバー運用で最も恐ろしい「ディスク容量不足」を未然に防ぐための監視スクリプトと、原因となるログファイルを自動で整理するローテーションスクリプトを作成します。
本講座のカリキュラム(全4回)
本シリーズでは、単なるコマンドの羅列ではなく「現場でそのまま使える」レベルの堅牢なスクリプト作成を目指します。
- 【今回】サーバーの異変を未然に防ぐ!「ディスク容量監視」と「ログローテーション」
- バックアップの自動化:tarとrsyncを駆使し、エラー通知まで実装する
- ユーザー管理の効率化:CSVファイルから大量のユーザーとSSH鍵を一括生成する
- セキュリティ監視:不正アクセス(SSH総当たり攻撃)を検知してIPを自動ブロックする
1. なぜ「監視」と「掃除」が必要なのか?
サーバーは24時間365日動き続けるものです。
しかし、何もせずに放置していると、アプリケーションが出力するログや、一時ファイル、バックアップデータなどが蓄積し、いずれ必ずディスク容量の上限(100%)に達します。
💡 ディスクがいっぱいになるとどうなる?
- 新しいファイルが作れなくなるため、データの保存に失敗する。
- ログが書き込めなくなり、WebサーバーやDBサーバーが停止する。
- 最悪の場合、OS自体が起動しなくなる(SSHログインすらできなくなる)。
人間が毎日 df コマンドを打って確認するのは非効率的ですよね。
そこで、シェルスクリプトを使って「危なくなる前に教えてくれる仕組み」と「不要なファイルを定期的に片付ける仕組み」を作ります。
2. ディスク使用率監視スクリプトを作る
まずは、現在のディスク使用量をチェックし、設定したライン(閾値)を超えていたら警告を表示するスクリプト disk_alert.sh を作成しましょう。
Step 1: 必要な情報をコマンドで取り出す
ディスク容量を確認するには df コマンドを使いますが、スクリプトで扱うには「数字だけ」が欲しいですね。
まずはコマンドラインで実験してみましょう。
[root@localhost ~]# df -h / Filesystem Size Used Avail Use% Mounted on /dev/vda1 30G 25G 5.0G 84% /
ここから「84」という数字だけを抜き出すには、awk や sed といったテキスト処理コマンドを組み合わせます。
[root@localhost ~]# df / | tail -1 | awk '{print $5}' | sed 's/%//'
84
うわっ、急に難しくなりました!awk とか sed って何ですか?パイプ | が3つもあります!
分解して考えれば簡単よ。
1. df / :ルートディレクトリの情報を表示
2. tail -1 :ヘッダー行を飛ばして、データの行(最後の一行)だけを取得
3. awk '{print $5}' :空白で区切られた「5番目の列(84%)」を取り出す
4. sed 's/%//' :邪魔な「%」という文字を空文字に置換して消す
これが「パイプライン処理」の真骨頂ね。
Step 2: スクリプトにまとめる
数値が取れるようになったので、vim disk_alert.sh でスクリプトを作成します。
今回は「使用率が80%を超えたら警告する」設定にしましょう。
#!/bin/bash
# ==========================================
# 設定エリア
# ==========================================
# 監視対象のパーティション(マウントポイント)
TARGET="/"
# 警告を出す閾値(パーセント)
THRESHOLD=80
# ==========================================
# メイン処理
# ==========================================
# 現在の使用率を取得(コマンド置換を使用)
current_usage=$(df "$TARGET" | tail -1 | awk '{print $5}' | sed 's/%//')
# 数値として比較する
# -ge は "Greater than or Equal" (以上) の意味
if [ "$current_usage" -ge "$THRESHOLD" ]; then
echo "[DANGER] ディスク容量が危険水準です!"
echo "対象: $TARGET"
echo "現在の使用率: ${current_usage}% (閾値: ${THRESHOLD}%)"
# 実際にはここでメール送信コマンドなどを実行する
# 例: echo "Disk Full" | mail -s "Alert" admin@example.com
else
echo "[OK] ディスク容量は正常です。"
echo "現在の使用率: ${current_usage}%"
fi
Step 3: 動作確認
実行権限を付与して動かしてみましょう。
[root@localhost ~]# chmod +x disk_alert.sh [root@localhost ~]# ./disk_alert.sh [DANGER] ディスク容量が危険水準です! 対象: / 現在の使用率: 84% (閾値: 80%)
THRESHOLD=90 に書き換えて実行し、ちゃんと [OK] に分岐するかも確認しておいてくださいね。
3. ログローテーションスクリプトを作る
監視だけでは「減っていること」はわかりますが、問題の解決にはなりません。
ディスクを圧迫する最大の要因である「ログファイル」を定期的に圧縮・削除するスクリプト log_rotate.sh を作成しましょう。
Linuxには標準で logrotate という機能がありますが、独自のアプリケーションログなどは自前で管理が必要な場合があります。
また、このスクリプトを書くことで「ファイル操作の自動化」の良い訓練になります。
やりたいこと(仕様)
- 対象のログファイル:
/var/log/myapp/app.log - 現在のログを、日付つきのファイル名に変更する(例:
app.log.20240115)。 - 空になった
app.logを再作成する(アプリが書き込み続けられるように)。 - リネームした古いログを
gzipで圧縮して容量を減らす。 - 30日以上前の古い圧縮ログは削除する。
スクリプトの実装
vim log_rotate.sh を作成します。
パスや日数の設定を変数にすることで、使い回しが効くようにします。
#!/bin/bash
# エラーが起きたらそこで停止させる(安全策)
set -e
# ==========================================
# 設定エリア
# ==========================================
LOG_DIR="/var/log/myapp"
LOG_FILE="app.log"
RETENTION_DAYS=30
DATE_SUFFIX=$(date +%Y%m%d)
# ディレクトリへ移動
cd "$LOG_DIR"
# ログファイルが存在するかチェック
if [ ! -f "$LOG_FILE" ]; then
echo "エラー: $LOG_FILE が見つかりません。"
exit 1
fi
echo "--- ログローテーション開始: $DATE_SUFFIX ---"
# 1. ログファイルをリネーム(退避)
mv "$LOG_FILE" "${LOG_FILE}.${DATE_SUFFIX}"
echo "ログを退避しました: ${LOG_FILE}.${DATE_SUFFIX}"
# 2. 空のログファイルを再作成
# touchコマンドはファイルがなければ空で作る
touch "$LOG_FILE"
# 権限設定(例:所有者をapache、パーミッションを644にするなど環境に合わせて)
# chmod 644 "$LOG_FILE"
echo "新しいログファイルを作成しました。"
# 3. 退避したログを圧縮(バックグラウンドではなく同期的に実行)
gzip "${LOG_FILE}.${DATE_SUFFIX}"
echo "ログを圧縮しました: ${LOG_FILE}.${DATE_SUFFIX}.gz"
# 4. 保存期間を過ぎた古いログを削除
# findコマンドの -mtime オプションを使う
# +30 は「30日より前」を意味する
echo "保存期間(${RETENTION_DAYS}日)を過ぎたログを検索して削除します..."
find . -name "${LOG_FILE}.*.gz" -mtime +$RETENTION_DAYS -delete -print
echo "--- 処理完了 ---"
💡 プロのひと工夫:set -e とは?
スクリプトの冒頭にある set -e は、「コマンドが一つでもエラーになったら、その時点でスクリプトを強制終了する」というおまじないです。
例えば、cd でディレクトリ移動に失敗したのに、そのまま次の mv や rm が実行されると、想定外のファイルを消してしまう大事故に繋がります。
実務のバッチ処理では必ずつける癖をつけましょう。
Step 4: テスト実行のための準備
このスクリプトを試すには、テスト用のディレクトリとファイルが必要です。
# テスト用ディレクトリ作成 [root@localhost ~]# mkdir -p /var/log/myapp # ダミーのログファイル作成 [root@localhost ~]# echo "test log" > /var/log/myapp/app.log # 実行権限付与 [root@localhost ~]# chmod +x log_rotate.sh # 実行 [root@localhost ~]# ./log_rotate.sh --- ログローテーション開始: 20240115 --- ログを退避しました: app.log.20240115 新しいログファイルを作成しました。 ログを圧縮しました: app.log.20240115.gz 保存期間(30日)を過ぎたログを検索して削除します... --- 処理完了 ---
ls -l /var/log/myapp/ で確認すると、元の app.log が空っぽ(0バイト)になり、app.log.20240115.gz ができているはずです。
4. 定期実行するための「Cron」設定
せっかく自動化スクリプトを作っても、人間が手動で実行していては意味がありません。
Linuxには「決まった時間にコマンドを実行する」ための仕組み、Cron(クーロン)があります。
Cronの書き方
crontab -e コマンドを打つと、Cronの設定ファイルを編集できます。
書式は以下の通りです。
分 時 日 月 曜日 コマンド
設定例
以下のように設定すると、理想的な運用になります。
- ディスク監視: 1時間に1回チェック
- ログローテーション: 毎日深夜3時に実行
# 毎時0分にディスク容量をチェック 0 * * * * /root/disk_alert.sh >> /var/log/cron_disk.log 2>&1 # 毎日AM 3:00 にログローテーションを実行 0 3 * * * /root/log_rotate.sh >> /var/log/cron_rotate.log 2>&1
後ろについている >> /var/log/... 2>&1 って何ですか?
なんか呪文みたいですね。
これは「スクリプトが出力したメッセージ(標準出力)も、エラーメッセージ(標準エラー出力)も、全てログファイルに追記保存する」という意味よ。
Cronで動かしたスクリプトがエラーで落ちても、画面には何も出ないから、こうしてログに残しておかないと原因究明ができなくなるの。
これも実務の鉄則よ!
まとめ:自動化こそエンジニアの使命
今回は「実践シェルスクリプト講座」の第1回として、サーバー運用の基本である監視と掃除を自動化しました。
| スクリプト名 | 役割 | 重要ポイント |
|---|---|---|
| disk_alert.sh | ディスク容量の監視 | df, awk, if文による数値比較 |
| log_rotate.sh | ログの退避・圧縮・削除 | mv, gzip, find -mtime, set -e |
これらをCronに仕込んでおけば、あなたが寝ている間もシェルスクリプトがサーバーを守ってくれます。
コウ君のような「ディスクフルでサーバー停止」という悲劇も、これでもう起こりませんね。
次回予告:万が一に備える「自動バックアップ」
ディスクの空き容量は確保できましたが、ハードウェアの故障やオペレーションミスでデータが消えるリスクは常にあります。
次回は、「tarコマンドによるフルバックアップ」と、プロ御用達の同期ツール「rsync」を使ったバックアップスクリプトを作成します。
さらに、処理が終わったらチャットツール(Slackなど)に通知を送る応用技にも挑戦しますよ!
今回のスクリプトは、自分のパソコン(WSLやMac)でも動くから、ぜひパスを変えて試してみてね。
失敗してもOSを壊さないように、練習用のディレクトリの中でやるのがコツよ!
▼スクリプトの実験場に最適!推奨VPS



コメント