「No space left on device」…絶望のカウントダウンを止めろ。
こんにちは!「LINUX工房」管理人の「リナックス先生」です。
全8回のlogrotate講座、お疲れ様でした。これでログ管理は完璧…と言いたいところですが、運用現場にはもう一つ、巨大な敵がいます。
それは「物理的なディスク容量不足」です。
いくらログを圧縮しても、サービスの成長とともにログは肥大化し、データベースの容量も増え続け、いつか必ず / (ルート) パーティションが100%になる日が来ます。
ディスクが満杯になると、ログが書けないだけでなく、データベースが停止し、最悪の場合はOS自体がクラッシュして起動しなくなります。
先生、緊急事態です!
logrotateの設定はしたんですが、そもそもサーバーのディスクが20GBしかなくて、もう残り100MBしかありません!
ログを消そうにも「監査のために1年は残せ」って言われてて…。
サーバーを作り直してデータ移行するしかないんでしょうか? そんな時間ありません!
落ち着いて、コウ君。Linuxはそんなにヤワじゃないわ。
現代のLinuxサーバー(AlmaLinuxなど)は、「LVM(論理ボリュームマネージャ)」という仕組みで動いていることがほとんど。
これを使えば、サーバーを止めずに、後からディスクを継ぎ足して容量を増やすことができるのよ。
さらに、logrotateには「olddir」という整理整頓機能もあるし、スクリプトを使えば別ディスクへの自動退避も可能なの。
本記事では、ディスク容量が逼迫した際やログが散乱した際の「3つのアプローチ」を徹底解説します。
- インフラ側からの解決策「LVMによるディスク拡張」
- ディレクトリを整理する基本機能「olddirの活用」
- 物理的に別の場所に逃がす「別ディスクへのログ自動退避」
📚 logrotate完全攻略講座(バックナンバー)
ログ管理の基礎から応用まで、全8回で体系的に学べます。
- 【第1回】サーバーの「時限爆弾」を解除せよ!ログローテーションの基礎と仕組み完全図解
- 【第2回】設定ファイルの魔術書!ローテーション周期・サイズ・保存期間の完全制御
- 【第3回】「ログが消えた!?」を防ぐ。copytruncateとcreateの決定的な違いとiノードの秘密
- 【第4回】ディスク容量を極限まで節約!圧縮設定と日付付与のテクニック
- 【第5回】再起動を自動化せよ!postrotateスクリプトによるプロセス制御
- 【第6回】権限トラブルを回避する!ユーザー指定とACL、出力先ディレクトリの管理
- 【第7回】動かない時の処方箋。デバッグモード活用とSELinux/ステータスファイルの罠
- 【第8回】最強のバックアップ構築。S3への自動転送と一元管理への応用
アプローチ1:LVMによるディスク容量の拡張
最も根本的な解決策は、「ディスクの容量そのものを増やす」ことです。
VPSやクラウド環境(AWS EBSなど)、あるいは仮想環境(VMware/VirtualBox)であれば、物理的なディスクサイズを増やしたり、新しいディスクを追加したりすることは容易です。
しかし、単にディスクを追加しただけでは、/ (ルート) の容量は増えません。
ここで登場するのが LVM (Logical Volume Manager) です。
1. LVMの仕組みを理解する(3層構造)
LVMは、物理的なハードディスクと、OSが見ているファイルシステムの間に「抽象化レイヤー」を挟む技術です。
以下の3つの概念を理解してください。
- PV (Physical Volume / 物理ボリューム):
物理的なハードディスクやパーティションそのものです。(例:/dev/sdb1)
「粘土の塊」だと思ってください。 - VG (Volume Group / ボリュームグループ):
複数のPVを束ねた、巨大な一つのプールです。(例:almalinux)
複数の粘土をまとめて一つの大きな「粘土の山」にします。 - LV (Logical Volume / 論理ボリューム):
VGから必要な分だけ切り出して作られる仮想的なパーティションです。(例:/dev/almalinux/root)
OSはこれを「ディスク」として認識し、ここにファイルシステム(XFSなど)を作ります。
つまり、「新しいディスク(PV)を追加」→「プール(VG)を大きくする」→「論理ボリューム(LV)を拡張する」という手順を踏むことで、既存のデータを消すことなく容量を増やせるのです。
2. 【実践】ディスク追加から拡張までの完全手順
それでは、AlmaLinux 9 環境で、新しいディスク(10GB)を追加して、ルートパーティションを拡張する手順をシミュレーションします。
※操作は全て root ユーザーで行います。非常に危険な操作を含むため、必ずバックアップを取ってから行ってください。
Step 1: 新しいディスクの確認
サーバーに新しいディスクを接続した後、OSが認識しているか確認します。
lsblk
出力例:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS sda 8:0 0 20G 0 disk ├─sda1 8:1 0 1G 0 part /boot └─sda2 8:2 0 19G 0 part ├─almalinux-root 253:0 0 17G 0 lvm / <-- これを増やしたい └─almalinux-swap 253:1 0 2G 0 lvm [SWAP] sdb 8:16 0 10G 0 disk <-- 新しく追加したディスク
sdb として10GBのディスクが見えています。
Step 2: PV(物理ボリューム)の作成
新しいディスク /dev/sdb をLVMで使えるように初期化します。
pvcreate /dev/sdb
Physical volume "/dev/sdb" successfully created. と出ればOKです。
Step 3: VG(ボリュームグループ)の拡張
既存のVG(ここでは almalinux)に、新しいPVを追加してプールを大きくします。
まずVG名を確認します。
vgs
出力例: VG #PV #LV #SN Attr VSize VFree almalinux 1 2 0 wz--n- 19.00g 0
VG名は almalinux です。
拡張を実行します。
vgextend almalinux /dev/sdb
Volume group "almalinux" successfully extended と表示されます。
もう一度 vgs を叩くと、VFree(空き容量)が10GB増えているはずです。
Step 4: LV(論理ボリューム)の拡張
増えたプールの容量を使って、ルートパーティション(LV)を拡張します。
LVのパスは df -h や lsblk で確認できます(例: /dev/mapper/almalinux-root)。
# 空き容量の100%を割り当てるコマンド lvextend -l +100%FREE /dev/mapper/almalinux-root
Logical volume almalinux/root successfully resized. と表示されます。
Step 5: ファイルシステムの拡張(これが最後!)
LVの器は大きくなりましたが、その中にある「ファイルシステム(XFS)」はまだ元のサイズのままです。
最後にファイルシステムを広げます。
AlmaLinux 9 (XFS) の場合:
xfs_growfs /
Ubuntu (ext4) の場合:
resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv
最後に df -h を実行し、/ のサイズが増えていることを確認しましょう。
これで、サーバーを止めることなくディスク容量不足を解消できました!
アプローチ2:olddir でログファイルを整理整頓する
次に紹介するのは、logrotate標準機能である olddir です。
これは、「ローテーションした古いログを、指定したディレクトリに移動して保存する」機能です。
1. olddir の基本と設定
/var/log/httpd/ の中に、access.log.1, access.log.2.gz ... と大量のファイルが散らばっていて見づらい!という場合に有効です。
サブディレクトリ(例:archives)を作ってそこに放り込むことで、メインのディレクトリをスッキリ保てます。
設定例:
/var/log/httpd/*.log {
daily
rotate 30
compress
# 古いログの移動先を指定(ディレクトリは事前に作成しておくこと)
olddir /var/log/httpd/archives
# 移動したファイルに権限を与える(必要に応じて)
create 644 root root
}
2. 重要な制約(別デバイス不可)
非常に便利な olddir ですが、致命的な制約が一つあります。
それは、「ログファイルと同じ物理デバイス(ファイルシステム)上にないと動かない」ということです。
例えば、/var/log/ が / パーティションにあり、/mnt/backup/ が別のHDDだとします。
この場合、olddir /mnt/backup/ と設定すると、logrotateはエラーを出して停止します。
⚠️ エラー内容
error: /var/log/httpd/access.log is on different filesystem than /mnt/backup/
これは、logrotateが内部で単純な「リネーム(mv)」操作を行っており、パーティションを跨ぐ移動(コピー&削除)には対応していないためです。
したがって、「ディスク容量不足の解消」のために別ディスクへ olddir する、ということはできません。
それを実現するのが、次のアプローチ3です。
アプローチ3:別ディスクへのログ退避と階層化管理
では、「ルートパーティションをこれ以上拡張できない(あるいは高価なSSDを節約したい)」場合に、安価なHDDなどの別ディスクへログを逃がすにはどうすればいいでしょうか?
ここで、logrotateのスクリプト機能が火を噴きます。
1. 要件定義と戦略
今回は以下の高度な階層化管理(ティアリング)を実現します。
- アプリケーションのログ(
/var/log/myapp/*.log)を管理する。 - 直近30日分は、標準の場所(
/var/log/myapp/)に残す。 - 31日以上経過したログは、別ディスク(
/mnt/archive/)に移動する。 - 移動したログは、合計365日経過したら完全に削除する。
2. 別ディスクのマウント準備
まず、新しいディスク(/dev/sdb とします)をフォーマットし、アーカイブ用ディレクトリとしてマウントします。
# パーティション作成(全領域を使用) echo -e "n\np\n1\n\n\nw" | fdisk /dev/sdb # XFSでフォーマット mkfs.xfs /dev/sdb1 # マウントポイント作成 mkdir -p /mnt/archive # マウント mount /dev/sdb1 /mnt/archive # 自動マウント設定 (/etc/fstab) echo "/dev/sdb1 /mnt/archive xfs defaults 0 0" >> /etc/fstab # ログ保存用ディレクトリ作成 mkdir -p /mnt/archive/myapp # 権限調整(必要に応じて) chmod 755 /mnt/archive/myapp
3. 【実践】logrotateによる階層化移動の実装
logrotateの設定ファイルを作成します。
ポイントは、lastaction ブロックの中で find コマンドを駆使して「移動」と「削除」を行うことです。
設定ファイル (/etc/logrotate.d/myapp):
/var/log/myapp/*.log {
daily
missingok
rotate 30
notifempty
compress
delaycompress
dateext
dateformat -%Y%m%d
# 権限設定(アプリのユーザーに合わせる)
create 644 myappuser myappgroup
sharedscripts
postrotate
# アプリケーションのリロード(createモードの場合)
/bin/systemctl reload myapp.service > /dev/null 2>/dev/null || true
endscript
lastaction
# 【処理1】30日を超えたログを別ディスクへ移動
# /var/log/myapp/ 内にある、30日以上前に更新された圧縮ログ(.gz)を探して移動
/usr/bin/find /var/log/myapp/ -name "*.gz" -mtime +30 -exec mv {} /mnt/archive/myapp/ \;
# 【処理2】アーカイブ先で365日を超えたログを削除
# /mnt/archive/myapp/ 内にある、365日以上前のファイルを削除
/usr/bin/find /mnt/archive/myapp/ -name "*.gz" -mtime +365 -delete
endscript
}
スクリプトの解説:
- rotate 30:
logrotateとしての管理は「30世代」です。31回目を回そうとした時、logrotateは一番古いログを「削除」しようとします。
しかし、その前にlastactionが走ります。 - find ... -mtime +30 -exec mv ...:
-mtime +30は「更新日時が30日(24時間×30)より前のファイル」を探します。
logrotateが削除する直前(あるいは削除対象にならなくても古くなったもの)を、mvコマンドで強制的に別ディスクへ退避させます。 - find ... -mtime +365 -delete:
移動先のディスク(/mnt/archive)は logrotate の管理外です。
放っておくと無限に溜まってしまうため、ここで一緒に「365日経過したファイルの削除」も行います。
⚠️ 注意点:rotate設定との兼ね合い
lastaction でファイルを移動(mv)してしまえば、元の場所からは消えるため、logrotate本体の rotate 処理(削除)と競合することはありません。
ただし、タイミングによっては「移動しようとしたら既にlogrotateに消されていた」あるいは「logrotateが消そうとしたら既に移動されていた」となる可能性があります。
安全策として、logrotate側の設定を rotate 32 程度(スクリプトの条件より少し長め)にしておくと、logrotateによる削除よりも先に確実に mv を実行できます。
4. 動作確認とトラブルシューティング
この複雑な設定が正しく動くか、必ずテストしましょう。
findコマンド単体でのテスト:
いきなり logrotate を回す前に、find コマンドが意図したファイルを拾うか確認します。
# 移動対象の確認(mvはしない) find /var/log/myapp/ -name "*.gz" -mtime +30 -print # 削除対象の確認(deleteはしない) find /mnt/archive/myapp/ -name "*.gz" -mtime +365 -print
テスト用に touch -d "2023-01-01" test.log.gz などで古い日時のファイルを作って実験すると良いでしょう。
SELinuxの壁:
別ディスク(/mnt/archive)へのアクセスは、デフォルトのSELinuxポリシーではブロックされる可能性が高いです。
ログローテート実行時(cron)に拒否されるのを防ぐため、ラベルを貼ります。
# アーカイブディレクトリにログ用ラベルを付与 semanage fcontext -a -t var_log_t "/mnt/archive/myapp(/.*)?" restorecon -Rv /mnt/archive/myapp
まとめ:容量不足は「技術」で解決できる
今回は、ディスク容量不足という危機的状況を脱するための、2つの強力な手法を学びました。
今回の重要ポイント:
- LVMを使えば、システムを止めずにディスク容量を増やせる(PV→VG→LV→ファイルシステムの順)。
xfs_growfsコマンドで、増えた容量をOSに認識させるのを忘れずに。olddirは整理には便利だが、別ディスク(別パーティション)へは使えない。lastactionとfindコマンドを組み合わせれば、高度な階層化ストレージ管理が自動化できる。
「ディスクがいっぱいになったら消す」という受動的な対応から、「容量が増やせる構成にしておく」「自動的に安いディスクへ逃がす」という能動的な設計へ。
これが、初心者エンジニアとプロフェッショナルを分ける壁です。
この付録記事の技術を使えば、あなたはもう「No space left on device」の文字に怯えることはありません。
自信を持って、大規模なサーバー運用に挑んでください!
▼ 実践的なインフラ技術を身につける ▼
LVM操作を試す
「VPS」で自分専用環境
ストレージ知識を年収に
「ITエンジニア転職」

コメント