httpd.confのvirtualhost設定で、指定していたログ保存パス(ディレクトリ)が存在しなかった場合に、対象のバーチャルドメインのアクセスログをなんとか抽出する方法はありませんか?
SSLやApache共通のログは見ましたが、NGでしたので、望みはないと思うのですが、どこかに復旧可能なリソース(メモリやスワップ?)がないものかと思って質問しました。
※不可という回答は不要です。
いくつか条件を満たしていれば、復元可能です。
( = その後ログローテートや誤操作でログファイルが消えた )
このような状態にある場合、ファイル記述子を使って、
% head /proc/$PID/fd/XXXX
// 必要なログファイルに割り当てられていた FD を見つける
% dd if=/proc/$PID/fd/5 of=/home/lost-log.txt
// 当該 FD をたぐって、ファイルに落とす
・・・というような操作が可能です。
( 上記の例は Solaris の場合ですが、linux などでも同様の手法がとれるかと思います )
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1248234
こちらは如何でしょうか?
質問が悪かったようです。
バーチャルホストのログ保存ディレクトリがない状態で運用されていたApacheの(出力されていない)ログをなんとか得る方法がないものかという質問です。
ここで、気づいたのですが、そもそもログ用ディレクトリが存在しなかった場合、Apacheそのものが起動しないんでしたっけ?(ほぼ必ずconfigtestも実施しているはずなので、ディレクトリが存在しなければ、せめてWarningは出たような記憶も)
だとしたら、途中で消されたと考えるのが妥当でしょうか?
いくつか条件を満たしていれば、復元可能です。
( = その後ログローテートや誤操作でログファイルが消えた )
このような状態にある場合、ファイル記述子を使って、
% head /proc/$PID/fd/XXXX
// 必要なログファイルに割り当てられていた FD を見つける
% dd if=/proc/$PID/fd/5 of=/home/lost-log.txt
// 当該 FD をたぐって、ファイルに落とす
・・・というような操作が可能です。
( 上記の例は Solaris の場合ですが、linux などでも同様の手法がとれるかと思います )
ご回答ありがとうございます。
以下のような状況で、限りなくイメージに近いコアな復旧方法なのですが、スキル不足により要領を得ません。再回答いただけますと幸いです。
※ためしに手当たり次第に存在するfd以下を指定すればよいのでしょうか?
> apache のプロセス起動の時点ではログが存在していた
> ( = その後ログローテートや誤操作でログファイルが消えた )
現状もhttpdは起動したままの状態です。
> ログファイル削除後、apachectl graceful などのログファイルを開き直す操作を一切行っていない
とくにそういった操作はしていません。
> お使いの OS の procfs (に相当するもの) にファイル記述子を扱う機能がある
/proc/が存在すれば対象という認識で正しいでしょうか?
> % head /proc/$PID/fd/XXXX
/proc/$PID/fd/ までは、httpdの親プロセスで存在しています。
その配下にハード(?)シンボリック(?)リンクの数字ファイルがいくつも存在し、
> l-wx------ 1 root root 64 Sep 4 22:56 10 -> pipe:[57600687]
のようなものばかりです。
一部、Apache系ログへのリンクはありますが、これはすでに確認済みの(対象のアクセスログではない)ものです。
手順としては、試された感じであってます。
/proc/$PID/fd/XXXX がたくさんあるのが、それぞれファイル記述子が指す先のファイル(に相当するもの) になっています。
ファイル記述子(File Descriptor, fd ) とは、プロセスがファイルを読み書きする際に使う手足のようなもので、このディレクトリには fd の数だけファイルもどきが見えている、という感じになっています。で、そのファイルもどきは、それぞれの実際のファイルを指すリンクになっているわけですが、実際のファイルが既に rm などの操作で消されていても、リンクとしてはしつこく残った実体を掴んだままになっているので、前述のような方法でログが復元できる・・・という仕組みです。
# どうもこの辺は説明が難しくなりますね・・。
で、どれが欲しいファイルなのかを探す方法ですが、簡単な方法はないはず、ですので、気長にひとつひとつ見てみるのが王道かな、という感じです。問題のバーチャルホストにアクセスしてみて最終更新日付が変わるものが狙いのブツ、とか、そういう程度の方法は場合によっては使えるかもしれません。
# 本当は、あるプロセスのファイル記述子の番号と、ファイル名との対照関係を調べるコマンドがあるはずなのですが・・Linux で該当するコマンドが思いつかないです・・。あとは、strace などのデバッグ系の手法もつかえるはず、ですね。
蛇足ながら、私の経験でいうと logrotate の設定をミスってgraceful せずにローテートするような形にしてしまうと、こういうパターンができてしまいます。
> 問題のバーチャルホストにアクセスしてみて最終更新日付が変わるもの
/proc/$PID/fd/配下でls -lするたびに、すべてのファイル記述子が実行時のタイムスタンプで表示されてしまいます。
(シンボリック?ハード?)リンク先が正しく存在するのは、すでに確認済みのログファイルで、そのほかは、リンク切れと見られる(ターミナルの表示設定でリンク元も先も文字色反転)ファイルです。
これらが、先の回答への返信でも記述したように
> l-wx------ 1 root root 64 Sep 4 22:56 10 -> pipe:[57600687]
のようにpipeとなっています。(httpdプロセス内でのパイプ?)
ためしに、どれか1つをddしてみましたが、5分ほどしても無応答だったため、キャンセルしました。
すでに確認済みのログファイルに該当するfd配下のものをddすると、確認済みと同じ内容が確かにダンプされていました。
つまり、今回のケースでは復旧は不可ということでしょうか?
再三で恐縮ですが、アドバイスいただけますと幸いです。
ご回答ありがとうございます。
以下のような状況で、限りなくイメージに近いコアな復旧方法なのですが、スキル不足により要領を得ません。再回答いただけますと幸いです。
※ためしに手当たり次第に存在するfd以下を指定すればよいのでしょうか?
> apache のプロセス起動の時点ではログが存在していた
> ( = その後ログローテートや誤操作でログファイルが消えた )
現状もhttpdは起動したままの状態です。
> ログファイル削除後、apachectl graceful などのログファイルを開き直す操作を一切行っていない
とくにそういった操作はしていません。
> お使いの OS の procfs (に相当するもの) にファイル記述子を扱う機能がある
/proc/が存在すれば対象という認識で正しいでしょうか?
> % head /proc/$PID/fd/XXXX
/proc/$PID/fd/ までは、httpdの親プロセスで存在しています。
その配下にハード(?)シンボリック(?)リンクの数字ファイルがいくつも存在し、
> l-wx------ 1 root root 64 Sep 4 22:56 10 -> pipe:[57600687]
のようなものばかりです。
一部、Apache系ログへのリンクはありますが、これはすでに確認済みの(対象のアクセスログではない)ものです。