原本に書き込まない — ログと向き合う4つの作法

技術解説

開いただけで3バイト増えた。

そのログ、あなたが読んだあとも同じファイルですか。

「読む」つもりの操作が「書く」操作になっている瞬間は、思っているより多くあります。

原本を壊さないことは、フォレンジックの第一原則として語られます。しかし日々のログ調査でそれが崩れるのは、事件対応の現場ではなく、ごく普通の作業の途中です。今回はその4場面——開いただけで変わるファイル、文字化けを「直して」しまうこと、新人に渡すときの伝え方、そして振り返り資料に現物が残らないこと——を、それぞれ「なぜ作法が崩れるのか」から順に見ます。

先に結論: UwView は原本のバイト列に触りません。開いた瞬間から表示・検索でき、分割も抽出も変換もしないので、読んでもファイルは同じままです。文字コードはファイルを作り直さずに開いたまま切り替えられ、Pro の多段階検索は絞り込んでも原本の行番号を最後の段まで保持するので、振り返り資料に「どのファイルの何行目か」を書けます(実測値は特定環境での測定例で、環境により異なります。詳細は記事末尾)

本記事は作業の作法の話です。ログの取り扱い・保全手続き・持ち出しの可否は、所属組織および委託元の規程、ならびに適用される法令に従ってください。インシデントが法的手続きに発展しうる場合は、自己判断で操作せず所定の窓口に相談してください。


1. 「開いただけ」のつもりが、ファイルが変わっている

状況

調査のために、エディタでログを開きました。何も入力せず、そのまま閉じます。

翌日、チェックサムを照合した同僚から連絡が来ます。

「このファイル、ハッシュが変わっています。」

身に覚えがありません。何も書いていないからです。

なぜ起きるか

多くのツールが「開く」と「編集する」を区別していないからです。

閉じるときに保存の確認が出なくても、ファイルが変わることはあります。代表的なものはこれです。

  • BOMを足す — UTF-8として保存し直すとき、先頭に3バイト(EF BB BF)を付ける設定になっているツールがあります。中身の文字は1つも変わっていないのに、バイト列は変わります
  • 改行コードを揃える — CRLF混在のファイルを開いて保存すると、片方に統一されます。行数は同じでも、全行のバイト数が変わります
  • 末尾に改行を足す — 「ファイルの末尾は改行で終わるべき」という設定が既定で有効なエディタがあります。最後の1行が改行なしで途切れていた場合、その事実そのものが消えます
  • タイムスタンプが動く — 保存すれば mtime が変わります。保存しなくても、環境によっては atime が動きます。「いつ最後に書かれたログか」を推定する材料が失われます

さらに、調査中に無意識にやってしまう操作もあります。

# 見やすくするつもりの整形。原本が置き換わる
sed -i 's/\r$//' app.log

# ソートして重複を見たかっただけ。上書きしている
sort app.log -o app.log

sed -i は「その場で編集」という名前ですが、実際には一時ファイルを作って置き換えます。inode が変わるので、ハードリンクは切れ、パーミッションや拡張属性が既定値に戻ることがあります。 元に戻す手段はありません。

汎用ツールでの対処と限界

作業コピーを作り、原本を書き込み不可にするのが定石です。

# 原本のハッシュを先に取る(作業の前と後で照合する)
sha256sum /var/log/app/app.log | tee evidence/app.log.sha256

# 書き込み不可にする
chmod a-w /var/log/app/app.log

# 作業は複製の上で行う(属性も保つ)
cp -p /var/log/app/app.log /work/app.log

# 開く前後で属性が動いていないかを見る
stat -c '%n %s %y %i' /var/log/app/app.log

これは効きます。作業コピーを作る習慣があるだけで、事故の大半は防げます。

限界は3つ。

ひとつめ、複製には原本と同じだけの容量が要ること。40GBのログを調べるために40GBの空きを用意するのは、外付けディスクに退避している状況では現実的でないことがあります。圧縮して置いてあるなら、展開にはさらに数倍の空きが必要です(第23回)。

ふたつめ、chmod a-w は万能ではないこと。root や管理者権限で開けば書けます。ネットワーク共有やクラウドストレージ上のファイルでは、そもそもパーミッションの意味が違います。「書けないようにした」という安心が、実態と一致しないことがあります。

みっつめ、読み取り専用で開けるツールが意外と少ないこと。ビューアを名乗るツールでも、索引ファイルやセッションファイルを対象と同じディレクトリに置くものがあります。原本そのものは無改変でも、保全対象のディレクトリの中身が変わります。証拠保全の手続きでは、これも説明を求められる変化です。


2. 文字化けしたログは、証拠になるか

状況

古いシステムから引き継いだログに、文字化けが混ざっています。

iconv で変換して、読める形にして保存しました。これで調査できます。

ただし、変換できなかった行がいくつか静かに消えていました。

なぜ起きるか

変換が不可逆で、しかも失敗を黙って処理する既定値があるからです。

文字化けという現象は、たいていバイト列が壊れているわけではありません。バイト列は正確で、解釈だけが誤っています。 Shift_JIS のバイト列を UTF-8 として表示すれば化けますが、ファイルの中身は何も損なわれていません。

問題は、そこで「直して保存する」ことです。

  • iconv -c は変換できないバイトを捨てます — 文字が減り、行が短くなり、場合によっては行そのものが消えます。エラーは出ません
  • //TRANSLIT は似た文字に置き換えます — 「〜」が「~」になる程度なら読めますが、それは元のログに書かれていた文字ではありません
  • 混在ファイルには単一の指定が効きません — 1本のログの中で、アプリが出した行は UTF-8、OS が出した行は CP932、ということがあります。ファイル単位の -f を指定した時点で、どちらかが壊れます
  • ハッシュが変わります — 変換して保存した時点で、元のファイルとは別物です。「改ざんしていない」ことを示せなくなります(第16回

つまり、文字化けしたログはそのままなら証拠になり、読みやすく直した瞬間に証拠でなくなります。

汎用ツールでの対処と限界

保存せず、表示のときだけ変換するのが基本です。

# 標準出力へ流すだけ。ファイルは作らない
iconv -f cp932 -t utf-8 app-2019.log | less

# 推定だけする(変換しない)
nkf --guess app-2019.log

# 化けている箇所の生バイトを見る
sed -n '284512p' app-2019.log | xxd | head -5

判断はできます。xxd まで降りれば、それが SJIS なのか UTF-16 なのか壊れたバイトなのかは分かります。

限界は3つ。

ひとつめ、パイプに流した時点で原本の行番号を失うこと。iconv | grep -n で出るのは変換後の並びの番号です。報告書に書きたいのは原本の座標なので、数え直す必要があります。

ふたつめ、混在に対応できないこと。1本の中で文字コードが変わるファイルを、行ごとに切り替えて読む手段が標準ツールにはありません。結局、どちらかを化けたまま読むことになります(第3回第11回)。

みっつめ、検索が変換後にしか当たらないこと。日本語で検索したければ変換が要り、変換すれば行番号がずれる。「原本のまま日本語で探す」が、この経路では成立しません。


3. 新人に最初に教えるのは、開き方ではない

状況

新人に調査を任せます。「このログ、エラーの前後を見ておいて。」

30分後に聞きに来ます。「開けませんでした。」

もっと困るのは、開けてしまった場合です。手近なエディタで開き、見やすいように並べ替えて、上書き保存してくれています。

なぜ起きるか

教えているのが手順であって、作法ではないからです。

「grep でこう打つ」は伝わります。伝わらないのは、その手前にある3つです。

  • 禁止事項が道具に埋め込まれていない — 「原本を書き換えない」は口伝で伝わりますが、道具の側は何も止めてくれません。うっかり保存できてしまう構造のままで、注意力だけに頼っています
  • 見るべき場所の勘が渡せない — 熟練者は WARN の出方や、タイムスタンプの間隔の乱れを見ています。それは「どこを見るか」であって、コマンドではありません。ワンライナーを渡しても、結果は渡せますが過程は渡せません
  • なぜその行を疑ったかが残らない — 調査が終わったあと、手元に残るのは結論だけです。途中で試して外れた仮説は消えます。新人が学べるのは正解の一手だけで、外し方を学べません

結果として、教育は「隣に座って見せる」に戻ります。それが最も効率的だからではなく、他に渡す形がないからです(第22回)。

汎用ツールでの対処と限界

手順書とスクリプトに落とすのが、現実的な対処です。

# 調査用の入口を用意して、原本を直接触らせない
alias applog='less -S /work/readonly/app.log'

# よく使う観点をスクリプトにしておく(教材を兼ねる)
grep -n -E '\[(ERROR|FATAL)\]' /work/readonly/app.log | head -50

# 「なぜそこを見たか」をコメントとして残す
#   → 直前5分にWARNが増えていないかを見る
grep -n -E '\[WARN\]' /work/readonly/app.log | awk -F'[: ]' '{print $1, $2}' | uniq -c

これで下限は上がります。読み取り専用の複製を入口にするだけで、上書き事故はほぼ消えます。

限界は3つ。

ひとつめ、色分けや注目点が共有できないこと。手順書に「WARN に注目」と書けますが、画面上でどう見えていたかは渡せません。熟練者の画面と新人の画面が、同じファイルを開いても別物のままです。

ふたつめ、スクリプトは正解しか含まないこと。外れた仮説はコミットされません。新人が身につけるのは手順の再生であって、判断ではありません。

みっつめ、手順書が古くなること。ログの書式が変わればスクリプトは壊れ、壊れたスクリプトは信用されなくなります。そして口伝に戻ります。


4. 振り返りに「現物」が残っていない

状況

障害の振り返り資料を開きます。

原因の説明のところに、ログのスクリーンショットが貼られています。トリミングされていて、行番号が写っていません。 ファイル名も書かれていません。

半年後、似た障害が起きます。前回のログのどこを見たのか、もう誰にも分かりません。

なぜ起きるか

現物を添えるコストが、加工した断片を貼るコストより高いからです。

40GBのログを資料に添付することはできません。だから誰かが該当箇所を切り出します。そこで3つのことが同時に起きます。

  • 文脈が固定される — 切り出した範囲が、そのまま「見た範囲」になります。あとから「その2分前はどうだったか」を確かめたくなっても、資料からは戻れません
  • 原本との対応が切れる — スクリーンショットには座標がありません。行番号を含めて撮っていても、原本が再圧縮や再ローテートを経ていれば番号は一致しません
  • 原本が先に消える — 資料は数年残りますが、ログの保管期限は数か月のことがあります。検証しようとしたときには、元のファイルがありません

ポストモーテムに現物を添える文化がなかなか根づかないのは、意識が低いからではありません。現物を指す方法が、スクリーンショット以外に用意されていないからです。

汎用ツールでの対処と限界

該当箇所を座標つきで切り出し、原本を特定できる情報を添えるのが基本です。

# 該当行の前後を、行番号つきで切り出す
sed -n '41284440,41284470p' app.log | cat -n

# もっと正確に: 原本の行番号のまま出す
awk 'NR>=41284440 && NR<=41284470 { printf "%d\t%s\n", NR, $0 }' app.log

# 原本を特定できる情報を一緒に残す
sha256sum app.log; stat -c '%n %s %y' app.log

これで資料の質は上がります。「どのファイルの何行目か」が書いてあるだけで、半年後の自分が辿れます。

限界は3つ。

ひとつめ、awk のこの書き方は毎回全行を読むこと。40GBの末尾付近を切り出すたびにフルスキャンが走ります。「もう少し前も見たい」と思うたびに同じ待ちが発生するので、範囲を欲張って一度に大きく切り出す動機が生まれ、資料が読みにくくなります。

ふたつめ、行番号が保存操作で動くこと。再圧縮・再結合・文字コード変換のどれかを経ると、番号の意味が変わります。番号を書いても、原本が同じ形で残っていることが前提です。

みっつめ、切り出しは調査の再現ではないこと。資料に残るのは結果であって、そこへ辿り着いた検索条件ではありません。次に似た障害が起きたとき、条件から組み直すことになります。


4つに共通していたもの

場面 崩れる作法 崩れる原因 汎用ツールでの対処 残る問題
開いただけで変わる 読むことが書くことになる 「開く」と「編集する」が分かれていない 複製・chmod a-w・ハッシュ 複製に容量が要る。ツールが周辺に書く
文字化け 読みやすく直してしまう 変換が不可逆で、失敗が静か iconv を標準出力へ・xxd 行番号を失う。混在に対応できない
新人教育 口伝に戻る 注目点と外れた仮説が渡せない 読み取り専用の複製・手順書 色分けが共有できない。判断が渡らない
振り返り 現物の代わりにスクショ 現物を指す方法がない 行番号つき切り出し・ハッシュ 全行スキャン。番号が保存操作で動く

4つとも、壊れているのは原本と観測結果の境目です。

原本は事実そのもので、書き換えてはいけないもの。観測結果は「どこを見たか・どう見えたか・何で絞ったか」で、残して渡すべきものです。ところが手元の道具では、この2つが同じ場所に置かれます。読むために変換して保存する。見やすくするために並べ替えて上書きする。注目点を伝えるために画面を撮る。どれも、観測結果を原本の側に書き込もうとしている操作です。

裏を返すと、条件は2つです。

  • 読む操作が、原本のバイト列を一切変えないこと — 表示のための変換も、索引の作成も、原本の外で完結すること
  • 観測結果が、原本の座標を保ったまま外に残せること — 行番号・色分け・検索条件が、ファイルを加工せずに保存・再現できること

冒頭の「開いただけで3バイト増えた」に戻ります。あれは事故ではなく、読むために書く道具を使っていたというだけのことです。


使っている道具

私が開発している UwView(無料)は、巨大なテキストを開いた瞬間から表示・スクロール・検索できるビューアです。ファイル全体をメモリへ読み込まないので、RAM より大きいファイルでも開けます。索引はバックグラウンドで作られ、完成すると行番号が付きます(他のビューアの多くは索引が終わるまで先頭しか見えません)。

  • 原本のバイト列に書き込みません: 1章に直接効きます。BOMを足すことも、改行コードを揃えることも、末尾に改行を補うこともしません。分割も抽出もしないので、原本は1本のまま・無改変のまま扱えます
  • 文字コードは、ファイルを作り直さずに開いたまま切り替えられます(UTF-8 / Shift-JIS(CP932) / EUC-JP / UTF-16 を自動判定)。2章の「変換して保存」が要らなくなるので、読める状態にしても原本のハッシュは変わりません
  • 色分けは表示側の設定として保存できます: 3章の教材はここに置けます。「WARN は黄、特定のスレッドIDは水色」という見方そのものを、ファイルを加工せずに渡せます
  • 処理はすべて手元のマシンで完結します。調査対象のログを外部のサービスへ送りません

ここから先が UwView Pro の領分です。

  • 多段階検索(ドリルダウン)で、原本の行番号が最後の段まで残ります: 4章に効きます。何段絞り込んでも「原本の何行目か」が保たれるので、振り返り資料にスクリーンショットではなく座標を書けます(多段階検索の記事
  • 検索条件を保存して、あとから同じ状態を開き直せます: 3章の「過程が渡せない」と4章の「条件が残らない」の両方に効きます。条件が成果物として残るので、新人に渡すのも、半年後の自分が再現するのも、同じ操作になります(アーカイブ×セッション復元の記事
  • 索引と圧縮を .uwvz として保存します: 一度開いたファイルは2回目以降行番号付きのまま瞬時に開き直せます(47.73GBのテキストで実測0.02〜0.07秒。特定環境での測定例で、環境により異なります)。4章の「もう少し前も見たい」が安くなるので、範囲を欲張って切り出す必要がなくなります

正直に書いておきます。UwView は証拠保全のツールではありません。

  • 保全手続きの代わりにはなりません。 ハッシュの取得・保管・立会いといった手続きは別途必要です。1章の sha256sum を置き換えるものではありません
  • 改ざん検知はしません。 開いたファイルが本物かどうかを判定する機能はありません
  • .uwvz は原本とは別のファイルです。 原本のディレクトリを1バイトも変えたくない運用では、保存先を別の場所に指定してください。「周辺に何も作らない」わけではありません
  • 文字化けの自動修復はしません。 できるのは解釈を切り替えて読むことだけで、壊れたバイト列そのものを直すことはできません
  • 色分けの共有はファイルの受け渡しです。 チーム全体へ自動配布する仕組みはありません
  • 対応するのはテキストです。バイナリのダンプやデータベースのファイルは対象外です

コマンドラインから同じことをする

v1.6.0 で uvp コマンドが付きました(無料版には uvf)。GUI と同じ .uwvz を使うので、CLI で作った索引はそのまま GUI でも効きます。この記事の4章に対応させると、こう書きます。

# 1章: 開かずに中身を確かめる(原本のバイト列には触らない)
uvp /work/readonly/app.log 'FATAL'

# 2章: 化けている疑いのある箇所を、変換して保存せずに文脈ごと見る
uvp app-2019.log 'ERROR' -C 3

# 3章: 新人へ「見るべき場所」を、結果ではなく条件の形で渡す
uvp app.log -uniq '\[([A-Z]+)\]' -head 20

# 4章: 振り返りに貼る該当箇所を、原本を触らずに書き出す
uvp app.log 'OutOfMemoryError' -C 5 -out postmortem/2026-09-18-oom.txt.gz

# 行番号ジャンプ・文字コードの切り替えは GUI 側の機能。続きはここで渡す
uvp app.log -open

終了コードは grep と同じ 0=あり・1=なしに、2=上限に当たって打ち切った(既定は無制限。-limit N で上限を決めたときだけ)が加わります。if uvp app.log 'FATAL'; then がそのまま書けるので、1章の「触る前の確認」を作業手順に組み込めます。

正直に書くと、1問目は ripgrep のほうが 15〜20% 速いです(uvp は先に索引を作るため)。3GB程度でメモリに収まるファイルなら、2問目以降も rg のほうが速いままです。uvp が効くのは10GBを超えて、同じファイルに2回以上聞くときです(実測記事。Mac M4・外付けUSB SSD・OpenStreetMap XML での測定例で、環境により異なります)。

できるのは、原本を変えずに読むこと・その場所を原本の座標で示すこと・同じ見方をもう一度当て直せる形で残すことです。振り返り資料にスクリーンショットしか貼れていないなら、まず「どのファイルの何行目か」を書くところから始めてみてください。

そして、ストレージを専有している巨大ログを圧縮して保管し、さらに高速に検索したいなら UwView Pro をどうぞ。永続索引・圧縮キャッシュ検索・約1/9保管で、開き直しも検索も一段速くなります(全OS対応・買い切り/月額プランあり)。

リンク

  • 第1回: 巨大ファイルに沈む4つの定番ツールと、その先: https://uvp.y42u.net/blog/uwview-ps01-huge-file-tool-limits/
  • 第3回: 文字コード4つの罠と切り分け手順: https://uvp.y42u.net/blog/uwview-ps03-japanese-encoding-traps/
  • 第11回: レガシー文字コードを2026年に読む: https://uvp.y42u.net/blog/uwview-ps11-legacy-encoding-euc-utf16/
  • 第16回: 保全・切り出し・改ざん対策の4原則: https://uvp.y42u.net/blog/uwview-ps16-log-as-evidence/
  • 第22回: 引き継げるチームの4つの工夫: https://uvp.y42u.net/blog/uwview-ps22-shareable-log-investigation/
  • 第23回: 世代管理と棚卸しルールの作り方: https://uvp.y42u.net/blog/uwview-ps23-log-retention-automation/
  • 翌日そこから開き直す(アーカイブ×セッション復元): https://uvp.y42u.net/blog/uwview-archive-session-restore-workflow/
  • 絞り込んだ先からさらに絞り込む(多段階検索): https://uvp.y42u.net/blog/uvp-drilldown-search/
  • uvp コマンドを付けました(ripgrep との実測比較): https://uvp.y42u.net/blog/uvp-cli-release-vs-ripgrep/
  • ソースコード(GitHub): https://github.com/amru195704/UwView

開発者より: アプリ・Kindle本・オープンソースの一覧は GitHub: amru195704 にまとめています。


お願い
本記事の情報は参考目的で掲載しており、正確性・完全性を保証するものではありません。掲載したログ例・行番号・ファイルサイズ・ハッシュ照合の手順はすべて説明のための例であり、特定の実在する案件やシステムを示すものではありません。コマンド例は環境(GNU/BSD、statsediconvnkf の実装差、シェルの種類)により調整が必要です。オプション名や既定値は必ず手元の man で確認してください。エディタが保存時にBOMや改行コードをどう扱うかは製品と設定により異なり、atime の記録可否はマウントオプションに依存します。記載した実測値は特定の1環境での測定例であり、同じ結果を保証するものではありません。ディスクの種類・接続方式・ファイルシステム・ページキャッシュの状態・同時に動いている他のプロセスにより、結果は大きく変わります。証拠保全の手続き、ログの取り扱い・持ち出しの可否は、所属組織および委託元の規程、ならびに適用される法令に従ってください。法的手続きに発展しうる事案では、本記事の内容を自己判断の根拠とせず、所定の窓口および専門家にご相談ください。誤記・不正確な情報がございましたら、コメント欄よりご指摘いただければ、確認のうえ修正いたします。

タイトルとURLをコピーしました