障害の調査が終わりました。報告書も出しました。手元に残っているのは、その調査に使った数十GBのログです。
さて、これをどうするか。
多くの現場で、この判断はその場の気分で行われています。今週は容量に余裕があるから残す。来月ディスクが逼迫したら、そのとき古い順に消す。判断基準が言語化されていないので、毎回ゼロから悩み、担当者が変われば結論も変わります。
この記事では、読み終わったログの置き場所をめぐる4つの場面を並べます。積み上がる・圧縮したら読めなくなる・遅いディスクに退避する・移設で行き場を失う。どれも手持ちのツールで一応は対処できます。そのうえで、その手がどこで止まるかまで踏み込みます。
1. 「とりあえず残す」が積み上がる — 保持期間を決めていないログ
状況
df -h を見たら、データ領域の半分近くがログでした。内訳を見ると、logrotate が管理している正規のログはむしろ少数派で、大半は調査のときに誰かが手でコピーしたものです。app.log.20250912.bak、investigation/、old_server_logs/。いつの何の調査で使ったのか、もう誰も思い出せません。
なぜ起きるか
消す判断と残す判断は、間違えたときのコストが対称ではないからです。
消して後から必要になった場合、取り返しがつきません。監査で求められた、同じ障害が再発した、顧客からの問い合わせが半年後に来た——どれも「あのときのログがあれば」で終わります。一方、残して結局使わなかった場合に失うのは、ディスクの一部だけです。
このコストの非対称性は本物なので、人間は合理的に「残す」へ倒れます。問題は倒れ方で、基準がないまま倒れると、消してよいものまで永久に残ります。そして数年後、誰も中身を把握していない数百GBの塊が、消すのも怖い状態で居座ることになります。
汎用ツールでの対処と限界
仕組みで削る手はあります。
find /var/log/archive -name '*.log' -mtime +90 -print # まず対象を見る
find /var/log/archive -name '*.log' -mtime +90 -delete # 確認してから消す
du -sh /var/log/* | sort -h | tail -20 # 何が太っているか
logrotate の rotate と maxage を設定すれば、正規のログは自動で回ります。
限界は、この数字を決める根拠のほうが用意されていないことです。90日でよい理由を説明できないと、結局「怖いから残す」に戻ります。決めるには最低3つの軸を分けて考える必要があります。
- 法令・契約:業種によって遡及を求められる年数が違います。ここは交渉の余地がなく、いちばん外側の制約になります。
- 再現性:そのログでしか再現できない事象の寿命です。該当バージョンがすでに全台から落ちているなら、そのログの調査価値は実質ゼロです。
- コスト:容量そのものより、バックアップとレプリケーションに乗って何倍にもなることが効きます。1本のログが3か所に複製されている構成は珍しくありません。
そして、この3軸を真面目に検討して「残す」と決めた瞬間から、次の3つの問題が始まります。
2. ディスクの半分がログで埋まっている — 圧縮したら読めなくなる問題
状況
容量が逼迫したので、古いログを gzip で固めました。テキストログはよく縮むので、それだけで空きが戻ります。半年後、「あのときのログを見たい」と言われました。解凍しようとして気づきます——展開先の空きが、もうありません。
なぜ起きるか
gzip も bzip2 も zstd も、既定の使い方ではストリーム圧縮です。ファイルの途中のバイト位置を直接指すことができず、n バイト目を読むには先頭から順に展開していく必要があります。
zgrep が便利に見えるのは、この全展開を裏でやってくれているからです。便利なのですが、中身は毎回の全展開なので、同じアーカイブを1日に5回検索すれば、5回ぶん全部を展開しています。しかもその展開結果は捨てられます。
もっと効くのは、ランダムアクセスができないこと自体です。ログ調査で本当にやりたいのは「12時34分あたりへ飛ぶ」「このIDが出る行の前後20行を見る」であって、全行を順に読むことではありません。ところが圧縮した瞬間、行番号で飛ぶ・位置で飛ぶという操作が失われます。
汎用ツールでの対処と限界
分割してから圧縮すれば、部分的な取り出しはできます。
split -l 5000000 app.log part_ && gzip part_* # 500万行ずつに割って圧縮
zstd --long=27 -19 app.log # 長距離マッチで圧縮率を上げる
zstd -d --stdout app.log.zst | less # 展開しながら読む
zstd には seekable format という拡張もあり、対応ツールがあればブロック単位で途中から展開できます。
限界は3つです。ひとつめ、分割すると「1本のログ」という単位が壊れます。part_ac の 1,203 行目は原本の何行目なのか、人間が計算することになります。ふたつめ、展開しながら読む方式では検索ができません。less に流し込んだ先で / を打っても、それは展開済みの範囲に対する検索です。みっつめ、seekable format のような賢い方式は、読む側のツールがそれを知っている必要があることです。ビューアが .gz を「開ける」と言っていても、実際には裏で一時ファイルに全展開しているだけ、というのはよくあります。
要するに、現状の一般的な選択は「小さくして読めなくする」か「大きいまま読める」の二択になっています。
3. 「念のため取っておく」ログの置き場所 — NASと遅いディスク
状況
消せないログを NAS と外付けHDDに逃がしました。容量問題は解決しました。年に数回、そこを開く日が来ます。ファイルをダブルクリックして、コーヒーを淹れに行きます。
なぜ起きるか
I/O が律速だからです。 これは道具の出来とはほとんど関係がありません。
実効 100MB/s のネットワークストレージに置いた 48GB のファイルを全部読むには、単純計算で 8 分強かかります。ギガビットのLANなら理論値でも 125MB/s なので、この桁は動きません。CPU がどれだけ速くても、線が細ければそこで待ちます。
ここで効いてくるのが、多くのツールが「読み終わってから見せる」設計になっていることです。見たいのが末尾の1画面だけでも、あるいは特定の1行だけでも、全体を読み終わるまで何も表示されません。48GB のうち実際に必要なのが数KBだったとしても、8分待ちます。
さらに、前回扱った文字コードの確認のように、開き直しが発生する作業と組み合わさると悲惨です。判定を切り替えるたびに 8 分では、確認そのものを諦めることになります。
汎用ツールでの対処と限界
部分だけ取りに行けば、待ちは減ります。
tail -c 10M /mnt/nas/app.log > tail.log # 末尾10MBだけ手元へ
dd if=/mnt/nas/app.log bs=1M skip=20000 count=50 of=part.log # 位置指定で抜く
rsync -P /mnt/nas/app.log ./ # 引き戻す(再開できる)
限界は、位置が分かっている場合にしか使えないことです。dd の skip に入れる数字は、たいてい調査の結果として分かるものであって、調査の入り口では分かりません。「20000MB 目あたりだろう」と当たりをつけて抜き、外れていたらもう一度——を繰り返すことになります。
そして mmap に頼る実装は、ネットワーク越しでは期待した挙動になりません。NFS/SMB 上の mmap はページフォルトのたびにネットワーク往復が発生し、ローカルディスクのつもりで書かれたコードがそのまま遅くなります。「手元にコピーしてから開く」が結局いちばん確実、という結論に落ち着き、容量問題を解決するために逃がしたはずが、読むたびに手元へ戻ってくることになります。
4. サーバ移設で行き場を失う旧ログ
状況
サーバの移設が決まりました。アプリケーションもデータベースも移行計画に入っています。停止予定日の2週間前、誰かが気づきます。「旧サーバのログ、どうします?」
なぜ起きるか
ログが「資産」として棚卸しされていないからです。移行計画に載るのは、動かすと止まるもの——アプリ、DB、証明書、DNS、cron——であって、ログは止めても何も壊れません。だから最後まで議題に上がりません。
しかし監査の観点では、ログは移設を理由に消えてよいものではありません。しかも旧環境固有の事情がくっついています。ローテートの命名規則(app.log.1 〜 app.log.52 の順序は移設先で意味を持つのか)、シンボリックリンク(実体はどこにあったのか)、文字コードとロケール(旧サーバの LANG に依存した出力が混ざっていないか)。そして最後に、読むための道具が旧サーバにしかないという問題。lnav の設定、誰かが書いた awk スクリプト、grep のエイリアス集。サーバを落とすと、それらも一緒に消えます。
汎用ツールでの対処と限界
やること自体は単純です。
tar -cf - /var/log/app | zstd -19 -T0 > applog.tar.zst # 固めて圧縮
sha256sum applog.tar.zst > applog.tar.zst.sha256 # 完全性の証明を添える
rsync -avP applog.tar.zst backup:/archive/ # 転送(再開できる)
チェックサムを一緒に残すのは、後から「このログは移設時から改ざんされていない」と言うために要ります。証跡として扱う可能性があるなら、この一行を省略しないほうがいい。
限界は、この作業が「あとで読める」ことを保証していないことです。applog.tar.zst は保管はできています。しかし2年後に監査で「この日の分を出してください」と言われたとき、やることは——展開先の空きを確保して、数百GBを展開して、目的の1ファイルを探して、開く。第2章で見た問題が、そっくりそのまま2年後の自分に転送されているだけです。
そしてもうひとつ。移設の場で必ず出る「どこまで持っていくか」という問いには、第1章の3軸(法令・再現性・コスト)を持っていないと答えられません。基準がないと、全部持っていくか、期限に押されて雑に切るかの二択になります。
4つに共通していたもの
| 場面 | 現れ方 | 止まる場所 |
|---|---|---|
| 保持期間が決まっていない | 出所不明のログが積み上がる | 「何日で消してよいか」の根拠がない |
| 圧縮して容量を空けた | 半年後に展開先の空きがない | 小さくすると読めなくなる二択 |
| NAS・外付けへ退避した | 開くたびに待たされる | 全読み前提の設計とI/O律速 |
| サーバ移設で持ち出した | 保管はできたが読める保証がない | 2年後の自分に問題を転送しただけ |
4つとも、突き詰めると同じ一点で詰まっています。「小さく置くこと」と「すぐ読めること」が、いまの道具では両立していないことです。
だから判断が「消す or 残す」の二択になります。圧縮が読めなくなることと同義でなければ、この二択は成立しません。第1章の3軸(法令・再現性・コスト)で保持期間を決める作業も、圧縮した状態のまま読めるという前提が入るだけで、ずいぶん楽になります。コストの軸が1桁下がり、「迷ったら残す」の代償が小さくなるからです。
そしてこれは、この連載で繰り返し出てきた形でもあります。第1回で見た「開くのに全読みを要求する道具」、第2回の「一覧と現場の往復コスト」、第3回の「解釈を切り替えるたびの読み直し」。保管の話に見えて、実は読むときの前提が保管の判断まで縛っている、という構図です。
使っている道具
私が開発している UwView(無料)は、この「全読みを待たされる」前提を外すために作ったビューアです。巨大なファイルでも開いた瞬間から全体を表示・スクロール・検索でき、索引はバックグラウンドで作られて、完成すると行番号が付きます。NASや外付けの遅いディスクでも、必要な位置だけを読みに行くので、末尾の1画面を見るために全体を待つことはありません(ただしI/Oが律速なのは変わらないので、全文検索は物理時間ぶんかかります)。原本には書き込まないので、証跡として扱うログもそのまま開けます。
そして、ストレージを専有している巨大ログを圧縮して保管し、さらに高速に検索したいなら UwView Pro をどうぞ。永続索引・圧縮キャッシュ検索・約1/9保管で、開き直しも検索も一段速くなります(2回目以降は行番号付きで瞬時に開けます。チェックサム付きなので保管中の破損も検出できます。全OS対応・買い切り/月額プランあり)。
リンク
- 第1回: 巨大ファイルに沈む4つの定番ツールと、その先: https://uvp.y42u.net/blog/uwview-ps01-huge-file-tool-limits/
- 第2回: ログの因果を遡る4つの技法: https://uvp.y42u.net/blog/uwview-ps02-log-causality-tracing/
- 第3回: 文字コード4つの罠と切り分け手順: https://uvp.y42u.net/blog/uwview-ps03-japanese-encoding-traps/
- 消すか残すかの第三の選択肢: https://uvp.y42u.net/blog/uwview-pro-archive-teaser/
- 圧縮率と速度の実測(条件つき): https://uvp.y42u.net/blog/uwview-pro-benchmark-3sizes/
- ソースコード(GitHub): https://github.com/amru195704/UwView
開発者より: アプリ・Kindle本・オープンソースの一覧は GitHub: amru195704 にまとめています。
お願い
本記事の情報は参考目的で掲載しており、正確性・完全性を保証するものではありません。転送速度・圧縮率・保管年数は環境や業種の要件により大きく異なります。コマンド例は環境(GNU/BSD、zstdのバージョン、ファイルシステム等)により調整が必要な場合があります。法令上の保管義務については、必ず自組織の規程および所管の定めをご確認ください。誤記・不正確な情報がございましたら、コメント欄よりご指摘いただければ、確認のうえ修正いたします。

