いますぐ実践! Linuxシステム管理

[バックナンバーのトップへ] [Linux システム管理のトップへ]


いますぐ実践! Linux システム管理 / Vol.142 / 読者数:1295名

こんばんは、うすだです。

とあるブログにあったリンクから、以下を知りました。

ブログ通信簿 - gooラボ
http://blogreport.labs.goo.ne.jp/

ブログの通信簿を作成してくださるようです。
早速、栗日記ブログ(http://usupi.seesaa.net/)で試してみました。

すると…
成績は、概ね平均値といったところなのですが、性別が女性、 年齢が40歳と判定されてしまいました。(あ、年齢は誤差の範囲内でした。)
でも、おかげさまで、そう判定されてもおかしくない生活習慣だなあ、 ということに気づくことができました。

ブログをお持ちのかたは、是非、試してみてください。
自分では気づいていなかった何かが、見えるかもしれませんよ。

それでは、女性的なわたくしが、今回もはりきってお送りいたします。

今回のお題 - 削除したファイルを復元する

前回は、ファイルを消してもデータが残ることがあるから要注意だ! 的な内容を、 お送りしました。

Vol.141 - データをしっかり消去する
http://www.usupi.org/sysad/141.html

さて、今回は逆で、うっかり削除してしまったファイルを、 なんとかして復元する方法について、ご紹介しようと思います。


とはいっても、なんでもかんでも召喚できるというわけではありません。
少なくとも、ファイルシステムが ext2 に限定されます。

Ext2 ファイルシステムでは、ファイルを削除したときに、 使用していたデータブロックの情報まで消し去ることをしません。
ですので、使用していたデータブロックの情報が残っていて、なおかつ、 データブロックが再利用されていなければ、それらをつなぎ合わせることで、 削除してしまったファイルを復元することができます。

ちなみに、ext3 ファイルシステムの場合は、ファイルを削除しますと、 使用していたデータブロックの情報を消し去ってしまいます。
ですので、復元は一筋縄ではいきません。(今回は対象外とします。)


さて、削除したファイルの復元には、debugfs コマンドを使用します。

debugfs コマンドは、対話的に作業を行えますので、実際に試しながら、 復元方法をご紹介していきましょう。

前回と同様に、普通のファイルをファイルシステムに仕立て上げ、 その上で試していきたいと思います。

まずは、1MB のファイルを作成し、ext2 ファイルシステムにします。

  # dd if=/dev/zero of=tameshi.img bs=1M count=1
  # mkfs.ext2 -m 0 -F tameshi.img

このファイルを /mnt/tmp に mount して、なにかファイルをコピーしてみます。 (以下では、なんとなく /ets/hosts をコピーしています。)

  # mount -o loop tameshi.img /mnt/tmp
  # cp -p /etc/hosts /mnt/tmp

そして、きちんと記録されるよう、マウントし直してから、削除します。

  # umount /mnt/tmp
  # mount -o loop tameshi.img /mnt/tmp
  # rm -f /mnt/tmp/hosts

「あちゃー、消してしまったー!」とわざとらしく叫んだところで、 復元の手順に入ります。
アンマウントして、debugfs コマンドを実行します。

  # umount /mnt/tmp
  # debugfs tameshi.img
  ...
  debugfs:  

すると、debugfs: というプロンプトが出力されます。
ここで、lsdel というコマンドを入力しますと、 最近削除されたファイルの iノードなどの情報を、ずらっと出力してくれます。

  debugfs:  lsdel
   Inode  Owner  Mode    Size    Blocks   Time deleted
      12      0 100644   6446    7/   7 Sun Aug  3 14:57:49 2008
  1 deleted inodes found.

今回は、削除したファイルが1つだけですので、一目瞭然的にわかりますが、 実際にはずらずらっと出力されて、どれがそうなのかよくわからん、 ということも、しばしばありえます。

そんなときには、stat コマンドで、詳細情報を確認します。
iノード番号を <> で囲んだものを引数に指定して、stat を実行します。

  debugfs:  stat <12>
  Inode: 12   Type: regular    Mode:  0644   Flags: 0x0   ...
  User:     0   Group:     0   Size: 6446
  File ACL: 0    Directory ACL: 0
  Links: 0   Blockcount: 14
  Fragment:  Address: 0    Number: 0    Size: 0
  ctime: 0x489548dd -- Sun Aug  3 14:57:49 2008
  atime: 0x48954816 -- Sun Aug  3 14:54:30 2008
  mtime: 0x4874e2e4 -- Thu Jul 10 01:10:12 2008
  dtime: 0x489548dd -- Sun Aug  3 14:57:49 2008
  BLOCKS:
  (0-6):38-44
  TOTAL: 7

モードやファイルサイズ、更新時刻などの情報がわかります。
これらをたよりに、該当する iノードを特定してください。

さて、上記の場合、データブロックは、38〜44 の7個を使用しています。
これらをつなぎ合わせることで、復元を試みられますが、dump コマンドが、 それらを一括して行ってくださいます。ありがたいですね。
引数には、<> つきの iノード番号と、出力ファイル名を指定します。 以下では、/tmp/hosts というファイルに復元しようとしています。

  debugfs:  dump <12> /tmp/hosts

復元できた(かもしれない)ようですので、quit と入力して、 debugfs を終了させます。そして、ファイルが同じかどうか確認します。

  debugfs:  quit
  % diff /etc/hosts /tmp/hosts
  % 

同じようです。データブロックの中身は無事でしたー。ふぅ。
めでたし、めでたしです。

 

ちなみに、lsdel コマンドで、該当すると思われる iノードが出てこない場合でも、 復元したいファイルのiノード番号があらかじめわかっているなら、 dump コマンドによる復元(の試み)は可能です。
iノード番号を知るには、ls コマンドの -i オプションなどを用います。

  # ls -li /mnt/tmp
  12 -rw-r--r-- 1 root root  6446  7月10日 01:10 hosts
  11 drwx------ 2 root root 12288  8月 3日 14:56 lost+found/

hosts ファイルのiノード番号は 12番だ、ということがわかります。
とはいえ、削除前にそんな機転がきくかよ、という疑問は残りますが…。


以上、削除したファイルの復元手順をご説明しました。
ただ、最近のディストリビューションですと、 ext2 がデフォルトで使用されなくなりつつあり、あまり役に立たないかもしれません。

ではここで視点を変えて、うっかり消してしまわないようにする工夫を、 少し考えてみたいと思います。

 

まずは、削除するときや上書きするときに、ほんとに実行してよいのか、 逐一お伺いをたててもらうようにしてみましょう。

はい、ご想像通り、エイリアスを使う方法です。
たとえば、rm コマンドを、rm -i にエイリアスします。

  # alias rm rm -i

rm コマンドを、-i オプションつきで実行しますと、削除する前に、 必ずお伺いをたてるようになります。(以下は、エイリアス設定後です。)

  # rm /etc/passwd
  rm: remove regular file `/etc/passwd'? 

同様に、mv コマンドや cp コマンドにも、-i オプションをつけるとよいと思います。

  # alias mv mv -i
  # alias cp cp -i

これらの設定を、~/.bashrc などに書いておくとよいですね… と言いたいところですが、主要なディストリビューションでは、 上記がすでに設定済になっていました。

 

気をとり直して、次に、リンクを増やす方法です。

rm コマンドなどでファイルを削除しようとすると、 指定されたファイルのディレクトリエントリを削除します。
通常、ファイルは、1つのディレクトリエントリからのみ参照されているため、 その参照がなくなると、リンク数が 0 になって、 ファイル自体を消し去られてしまいます。

ですが、もし、別のディレクトリエントリからも参照されている場合は、 rm しても、別のディレクトリエントリからの参照が残っていますので、 ファイルが消し去られることはありません。

ということは、消されると困るファイルは、別からリンクしておけばよい (rm したときに、リンク数が 0 にならなければいい)ですよね。

普通、ファイルのリンク数は、1 です。

  # cd /etc
  # ls -l hosts
  -rw-r--r-- 1 root root  6446  7月10日 01:10 hosts

root の手前の数字が、リンク数です。いまは 1 ですね。
ここで、.hosts.backup というファイル名のリンクを作成します。

  # ln hosts .hosts.backup
  # ls -l hosts .hosts.backup
  -rw-r--r-- 2 root root  6446  7月10日 01:10 .hosts.backup
  -rw-r--r-- 2 root root  6446  7月10日 01:10 hosts

すると、リンク数が 2 になります。
これらは、名前は異なりますが、以下のように同じ iノード番号になっていますので、 同じファイルを指していることがわかります。

  # ls -1i hosts .hosts.backup
  230596 .hosts.backup
  230596 hosts

ということは、この状態で hosts を削除しても、 .hosts.backup からの参照がありますので、hosts の実体が消されることはありません。

  # rm -f hosts
  # ls -l hosts .hosts.backup
  /bin/ls: hosts: そのようなファイルやディレクトリはありません
  -rw-r--r-- 1 root root  6446  7月10日 01:10 .hosts.backup

ですので、再度リンクを作成すれば、めでたく復元できます。

  # ln .hosts.backup hosts
  # ls -l hosts .hosts.backup
  -rw-r--r-- 2 root root  6446  7月10日 01:10 .hosts.backup
  -rw-r--r-- 2 root root  6446  7月10日 01:10 hosts

ただし、リンクは、同一ファイルシステム内でしか作成できません。
(iノード番号は、そのファイルシステムの中でのみ有効です。)

また、シンボリックリンクでは、リンク数は増えませんので、 削除を阻止する力はありません。ご注意ください。

  # ls -l hosts
  -rw-r--r-- 1 root root  6446  7月10日 01:10 hosts
  # ln -s hosts .dame
  # ls -il hosts .dame
  7734322 lrwxrwxrwx 1 root root     5  8月 3日 17:41 .dame -> hosts
   230596 -rw-r--r-- 1 root root  6446  7月10日 01:10 hosts

リンク数は 1 のままですし、iノード番号も異なります。


以上、消してしまったファイルを復活できるかもしれない方法や、 消してしまわないための予防策を、ご紹介しました。

ちなみに、今回の元ネタは、以下です。

Linx Ext2fs Undeletion mini-HOWTO
http://www.linux.or.jp/JF/JFdocs/Ext2fs-Undeletion/index.html

しょ、正直に申し上げますと、今回は、上記の抜粋的な内容です。

もちろん、不足している点や情報の古い点などを、自分なりに補足して、 オリジナリティーを出すようにしたつもりです。

詳細を確認されたい場合や、 ファイルの復元手順を違う視点で眺めたいと思われた貴兄は、上記をご覧くださいませ。

宿題の答え

前回の宿題は、

  ファイルの中の一部分を消去したとき、前データがどうなるのか、確認
  してみましょう。

でした。

先頭や途中のデータを削除した場合は、後続のデータに上書きされますので、 きれいさっぱりなくなると思われます。
実際、以下のように試してみますと…

  (↓ファイルシステムを作成します。)
  # dd if=/dev/zero of=tameshi.img bs=1M count=1
  # mkfs.ext2 -m 0 -F tameshi.img
  (↓mount して shadow ファイルをコピーします。)
  # mount -o loop tameshi.img /mnt/tmp
  # cp -p /etc/shadow /mnt/tmp/
  (↓念のため mount し直します。(sync の代わりです))
  # umount /mnt/tmp
  # mount -o loop tameshi.img /mnt/tmp
  (エディタで /mnt/tmp/shadow の root の行を削除します。)
  (↓バックアップファイル shadow~ があるので消し去ります。)
  # ls /mnt/tmp
  lost+found/  shadow  shadow~
  # shred -u /mnt/tmp/shadow~
  # ls /mnt/tmp
  lost+found/  shadow
  (↓umount して、消した行がないか探します。)
  # umount /mnt/tmp
  # strings tameshi.img | grep root
  #

なにも出てきませんので、上書きされて消されてしまったようです。

では、途中ではなく最後の方だと、どうでしょうか。
終端を示す位置だけが変わって、データが残る…なんてことが、 ありうるかもしれません。念のため、試してみましょう。

  # mount -o loop tameshi.img /mnt/tmp
  # tail -1 /mnt/tmp/shadow
  test:秘密だよ:13996:0:99999:7:::
  (↑この test の行を、vi などで削除します。)
  # shred -u /mnt/tmp/shadow~
  # grep test /mnt/tmp/shadow
  # umount /mnt/tmp
  # strings tameshi.img | grep test
  #

…大丈夫なようです。
では、安心ですね…と言いたいところですが、 ファイルはデータブロック単位で管理されていますので、 ブロックをまたいでも大丈夫かどうかを、さらに念のため確認してみたいと思います。

まず、dumpe2fs コマンドで、ブロックサイズを確認します。

  # dumpe2fs tameshi.img
  ...
  Block size:               1024
  ...

1ブロックは 1024バイトのようです。
では、1024バイトより大きいファイルを作成してみましょう。
"test" という文字列 260個からなるファイル foo を作成します。

  # mount -o loop tameshi.img /mnt/tmp
  # perl -e 'print "test"x260' > /mnt/tmp/foo
  # ls -l /mnt/tmp/foo
  -rw-r--r-- 1 root root 1040  7月25日 01:23 /mnt/tmp/foo
  # umount /mnt/tmp
  # strings tameshi.img | grep test
  testtesttest...

"test" という文字を 260個書きましたので、foo のサイズは、 4*260 = 1040 バイトになります。

これを、上書きして、1ブロックにおさまるサイズにしてみます。
たとえば、"BAD" という文字列を16個、同ファイルに上書きします。

  # mount -o loop tameshi.img /mnt/tmp
  # perl -e 'print "BAD"x16' > /mnt/tmp/foo

すると…

  # umount /mnt/tmp
  # strings tameshi.img | grep test
  testtesttesttest

おお、データが残りました。見たところ、"test" が4個あります。

最初のブロックは、"BAD"x16 で上書きされてしまいましたが、 もう1つのブロックには、まだ元のデータが残っているようです。
元のサイズは 1040バイトで、 そのうち最初のブロックである 1024バイトが、 別のデータに上書きされてしまったと考えますと、 1040-1024 = 16 となり、上記の結果とサイズが一致します。

ちなみに、最初のデータを "test"x280 にしますと、 最終的には、"test" の数が 24個になりました。
4*280-1024 = 96 = 4*24 = "test"*24 ですので、つじつまが合います。

というわけで、単一のファイルの変更でも、古いデータが残ることがありました。 ですので、機密情報の扱いには、十分ご注意くださいませ。

今回の宿題

今回の宿題は、

  削除したファイルを復元しようとしたところ、データブロックがすでに
  再利用されていて途方に暮れる、という経験をしてみましょう。

です。

ようは、debugfs の dump で復元するまでの間に、 データブロックの中身が書き換わる行為をして、 復元したけど中身が違って時すでに遅し、的な状況を作り出してみてください。

経験こそすべてだ、と無理矢理自分に言い聞かせて、試していただけますと、幸いです。

あとがき

もう2年以上、当メルマガを書いていますが、最初の頃と比べて、 文章がうまくなったよなあ、という気がまったくしません。

たまに、過去のネタとダブっていないか、昔の文章を読みます。
ですが、おどろくほど成長していない自分に、げんなりしてしまいます。

そんな中、以下のようなサイトを見つけました。

人に伝わる文章の書き方
http://bunnsyou.fc2web.com/index.html

わかりやすい文章の書き方を、おそらく基本的なところから、逐一教えてくださる、 ありがたいサイトです。

上記を拝見して、いろいろ間違っていたこと、わかりにくい文章を書いてきたことに、 気づくことができました。

というわけで、今回は、それらを踏まえた文章に…とはなっていなくて、 ご覧のとおり、ほとんど(あるいはまったく)変わっていません。
ですが、なるべく少しでも反映して、 わかりやすい文章に近づけていこうという気持ちで、毎回書いていこうと思っています。

 

今回はイマイチだったねとか、こんなネタを扱ってほしいとか、 なんでもかまいませんので、なにか思うことがありましたら、お気軽に、 メールでご連絡いただけますと、たいへんありがたやです。

 

今回も、ここまで読んでいただき、ありがとうございました。
それでは、次回は 8月17日(日) 頃に、お会いしましょう!

 

「いますぐ実践! Linux システム管理」の解除は、以下からできます。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

バックナンバーは、こちらにほぼ全部そろっています。
http://www.usupi.org/sysad/backno.html

「栗日記」−栗の絵を描いてますが、秋に向けてがんばらないと…。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本