Chienomi

ホームディレクトリを破壊する事故の話

雑感::mythings

今回、「メインPCのホームディレクトリをacross filesystemでrm -rfされ、全データが消える」という事故を起こした。

「across filesystemでのホームディレクトリへの爆撃」は人生で4度目だが、過去3回と違い今回は(おそらく)私の過失ではない。

今回は事の顛末と、そのダメージについて述べる。

原因

今回はRubyスクリプトのmmfft9が、ホームディレクトリに対してFileUtils.rm_rfを実行してしまったというものだ。

ただ、これはスクリプトのバグというよりも、Rubyのglitchではないかと思っている。 というのも、原因となるmmfft9-run.rbからディレクトリ消去に関わる部分を抜粋すると

@ccwd = nil
Dir.chdir File.join(@state_dir, "run", dirname) && @ccwd = Dir.pwd
Dir.chdir @cwd
FileUtils.rm_rf @ccwd

という感じである。 このスクリプトにおいて

  • @state_dirまたはdirnamenilだった場合、File.joinはエラーになる
  • Dir.chdirが存在しないディレクトリ、または移動できないディレクトリに対するものであった場合、エラーになる
  • @ccwdnilのままであった場合、FileUtils.rm_rfはエラーになる

という挙動であるから、@ccwdがホームディレクトリになるという状況が考えられない。 そして、ホームディレクトリが消されてしまうのは、「Dir.chdirに失敗しているにも関わらず、@ccwdにcwd=ホームディレクトリがセットされて進行する」という状況があった場合だけである。

おそらくは再現困難なglitchの類だろう。

被害

実はメインPCで爆撃してしまったのは、across filesystemの先であった場合を除けば今回が初めて。 つまり、被害が結構大きい。 ただし、実際の被害はマウントポイントがメインPCのホームディレクトリであったときと比べれば小さい。

今回はメインPC上のユーザーデータ、約2.5TBが消滅した。 メインPCのストレージは年々大きくなっていて、現在はLinuxだけで7TBのSSD空間があるため、従来よりも容量的なダメージは大きい。

ただし、実際には致命的なダメージにはなりにくい。

まず、変更されないデータは原則としてファイルサーバー上にアーカイブされており、PC上にない。

作業で更新が多いテキストデータはバージョン管理システムを用いて管理されており、リポジトリは基本的にクラウドストレージで共有されている。

メインPCで扱うとは限らないデータも、クラウドストレージで共有されている。

さらに、一部のデータは他のPCにも存在している。

加えて、アーカイブ作業の途中で起きた事故であるため、アーカイブが進行しており、写真などのデータはすでにアーカイブ済みで普段よりもダメージが少し少なかった。 また、被害の中心となったのはゲームのプレイ動画だが、すでにキューは最後までいった状態で発生した事故で、P720でも並列処理していた。メインPCの処理能力はP720の2〜3倍であるため、1/3〜1/4程度のデータはすでに変換済みで無事だった。

以上を踏まえて失ったデータではっきりしているものは

  • ホームディレクトリ以下の設定ファイルで、メインPCにしかないもの
  • 約1年半分のスクリーンショット
  • ログの類
  • 帳票
  • 多数のユーティリティスクリプト
  • 多数のメモの類
  • 約250ファイルのダウンロードデータ
  • 数個の動画プロジェクト
  • 共有していないサイトデータ (e.g. 宇宙庭園, PureBuilder公式サイト)
  • 2年分のeメール
  • ウェブアプリ

逆にプログラムの類は消す前に間に合ったため無事だった。

タイミング……

実は、ちょうど最近このことを踏まえて気にしていた。

というのも、SSDにしかない、メインPCにしかないデータというのは消えてしまった場合に残らない。 大部分は冗長化されており、基本的に消えてしまう可能性があるのは「処理前データ」だけだが、特にDocumentsディレクトリ下のファイルには冗長化されていないユーザーデータが結構な量あり、危険だということである。

ちょうど事故が起こる前日に、寝室PCでは同様の問題に対する対処を加えていた。 ホームディレクトリでBtrfsのスナップショットを取るというものである。 ただ、この方法はメインPCでは取れない。メインPCのルートファイルシステムはext4だからだ。

この問題、というより、データが前時代の遺産を引きずっているという問題はここ2年くらいかけて順次対応しており、だいぶ進んできてはいた。 そのため、アーカイブから変換したデータを持つのではなく、アーカイブと同期してデータを持つ形になり、データを失っても簡単に取り戻せるようにしたりしていた。

最終的には、ローカルだけに存在するのは処理前データと一時データだけになるようにするのが目標ではある。 だが、達成はできていないため、ローカルだけに存在するデータは依然として少なくなく、そのうちDocumentsディレクトリ以下のデータは深刻な問題であった。

とはいえ、アーカイブ処理がそれなりに進んだタイミングであったこともあり、データ被害は普段よりは少なかったし、以前よりはだいぶ少なくなってはいる。

心理的な話でいうと、「そろそろまっさらから構築し直してみたいな」と思っていたところだったので、環境を失ったことに対する精神的なダメージはやや少ない。

だが、痛くないわけではない。

ゲームのプレイ動画は基本的には「仕方ない」で済む。 特に、今回の処理対象は基本的にオフラインゲームであり、しかも音ゲーのレコードプレイはP720側に残っているため、「時間さえかければ再び体験できる」内容ではある。 だから、大規模なデータ容量に対するダメージは、そこまで深刻ではない。

だが、スクリーンショット、eメール、帳票あたりは実際失ったことで困る可能性がある。 これらは「保存しているということを拠り所にしている」部分があり、失ったことで「確認できない」「証拠が出せない」などの問題が発生する可能性がある。

現実的に最も痛いのは、ログデータの消失だ。 このために統計的な過去との比較が恒久的にできなくなり、変遷をたどることができなくなる。 毎年恒例になっているChienomi Statsも、今年は非常に大きな変化があったにも関わらず出せない。

Chienomiの再ビルドに不安があるという問題もある。 ChienomiのビルドにはWordPressのエクスポートデータが必要だが、このデータはChienomiのリポジトリに含まれておらず、WordPressのエクスポートデータがバックアップされているかどうかわからない。

Chienomiを含め記事自体は無事なサイトが多いが、失ったサイトもあるし、アプリ系は手元にはない。 アプリの場合、現役のものはサーバー上にあるが、今アップしていないものは失われた。

過去の資料に関してもそれなりの数が失われた。

今回の被害を失った総括すれば、「致命的ではないが、大怪我をした」くらいのもの。

再発防止策

今回はRubyスクリプトで、しかも論理上起こり得ない形で発生したため、「注意する」というような方針で防げる類のものではない。

そこで、いくつかの再発防止策を講じた。

  • ホームディレクトリ以下にマウントポイントを置かない
    • ホームディレクトリは比較的事故に至りやすい
    • across filesystemでマウントされているデータまで巻き込まれる
    • ホームディレクトリ下にあるほうが便利ではあるが、分離したほうが安全
  • 一時データ以外をルートファイルシステムに固有のデータとして置かない
    • クラウドストレージのDocumentディレクトリを活用する
  • ホームディレクトリのスナップショットを取る
    • システムが壊滅したので、OSを再インストールし、Btrfsで構成した
    • ルートファイルシステム上に置くファイルを制限することで容量も小さくしてやりやすくした