time
は、特定のコマンドがどれだけのCPU時間を消費するかを知りたい場合に最適なコマンドです。
プログラムとその子によってアクセスされているファイルを一覧表示できる同様のものを探しています。リアルタイムで、または後でレポートとして。
現在私は使用しています:
#!/bin/bash
strace -ff -e trace=file "$@" 2>&1 | Perl -ne 's/^[^"]+"(([^\\"]|\\[\\"nt])*)".*/$1/ && print'
ただし、実行するコマンドにSudo
が含まれている場合は失敗します。あまりインテリジェントではありません(存在するファイルまたはアクセス許可の問題があるファイルのみを一覧表示できるか、それらを読み取るファイルと書き込むファイルにグループ化できればいいでしょう)。また、strace
は遅いため、より高速な選択で十分です。
私は自分のツールをあきらめてコーディングしました。そのドキュメントから引用するには:
SYNOPSIS
tracefile [-adefnu] command
tracefile [-adefnu] -p pid
OPTIONS
-a List all files
-d List only dirs
-e List only existing files
-f List only files
-n List only non-existing files
-p pid Trace process id
-u List only files once
ファイルを出力するだけなので、strace
からの出力を処理する必要はありません。
https://gitlab.com/ole.tange/tangetools/tree/master/tracefile
strace
を使用してシステムコールを追跡できますが、実際には速度の低下が避けられません。管理者特権でコマンドを実行する場合は、strace
をrootとして実行する必要があります。
Sudo strace -f -o foo.trace su user -c 'mycommand'
より速くなる可能性が高いもう1つの方法は、ファイルシステムアクセス関数をラップするライブラリLD_PRELOAD=/path/to/libmywrapper.so mycommand
をプリロードすることです。 LD_PRELOAD
環境変数は、昇格された特権で呼び出されたプログラムには渡されません。そのラッパーライブラリのコードを記述する必要があります( 「楽しみと利益のためにライブラリインターポーザーを構築する」の例です) ); Web上で利用可能な再利用可能なコードがあるかどうかはわかりません。
特定のディレクトリ階層内のファイルを監視している場合は、 LoggedFS を使用してファイルシステムのビューを作成し、そのビューを介したすべてのアクセスがログに記録されるようにすることができます。
loggedfs -c my-loggedfs.xml /logged-view
mycommand /logged-view/somedir
LoggedFSを構成するには、プログラムに同梱されているサンプル構成から始めて、 LoggedFS構成ファイルの構文 をお読みください。
別の可能性は、Linuxの 監査サブシステム です。 auditd
デーモンが開始されていることを確認してから、ログに記録する内容を auditctl
で構成します。ログに記録された各操作は、/var/log/audit/audit.log
に記録されます(通常のディストリビューション)。特定のファイルの監視を開始するには:
auditctl -a exit,always -w /path/to/file
監視をディレクトリに置くと、その中のファイルとそのサブディレクトリも再帰的に監視されます。監査ログを含むディレクトリを監視しないように注意してください。ロギングを特定のプロセスに制限できます。使用可能なフィルターについては、auditctl
のマニュアルページを参照してください。監査システムを使用するには、rootである必要があります。
私はあなたがlsof(おそらくプログラムのgrepとその子にパイプされている)が欲しいと思います。ファイルシステムで現在アクセスされているすべてのファイルを教えてくれます。プロセスがアクセスしたファイルに関する情報について( ここから ):
lsof -n -p `pidof your_app`
tracefile
を試しました。私にとっては、自分の_strace ... | sed ... | sort -u
_よりも一致がはるかに少なかった。 _-s256
_をstrace(1)
コマンドラインに追加しましたが、あまり役に立ちませんでした...
それからloggedfs
を試しました。最初に、ログに記録しようとしたディレクトリへの読み取り/書き込みアクセス権がないため、失敗しました。 chmod 755を実行した後、一時的にヒットしました...
しかし、私にとっては、次のことを行うのが最も効果的であると思われます。
_inotifywait -m -r -e OPEN /path/to/traced/directory
_
そして、目的のプロセスを実行した後、出力を後処理します。
これはトレースされたディレクトリ以外のファイルプロセスアクセスをキャッチしません。また、他のプロセスが同じディレクトリツリーにアクセスしたかどうかもわかりませんが、多くの場合、これはジョブを取得するのに十分なツールです完了しました。
編集:inotifywaitはシンボリックリンクのアクセスをキャッチしません(シンボリックリンクが解決された後のターゲットのみ)。プログラムがアクセスするライブラリを将来使用するためにアーカイブしたとき、私はこれに見舞われました。いくつかの特別なPerl globハッカーを使用して、通知されたライブラリーに沿ってシンボリックリンクを選択し、その特定のケースで作業を完了させました。
EDIT2:少なくともinotifywaitコマンドライン(たとえば、_inotifywait -m file symlink
_または_inotifywait symlink file
_)の出力からファイルとシンボリックリンクをinotifyする場合、コマンドラインの最初にあるファイルへのアクセスが表示されます(どちらに関係なく、file
symlink
にアクセスします)。 inotifywaitはIN_DONT_FOLLOWをサポートしていません-プログラムで試したところ、コマンドラインでの順序に関係なく、file
へのアクセスが表示されるだけです(期待どおりかどうかはわかりません)。
それはあなたに十分な制御を与えないかもしれませんが(まだ?)私は少なくとも部分的にあなたのニーズを満たすプログラムを書きました、linux-kernelのfanotifyとunshareを使用して特定のプロセスとその子によって変更された(または読み込まれた)ファイルのみを監視します。 straceと比較すると、かなり高速です(;
https://github.com/tycho-kirchner/shournal にあります
シェルの例:
$ shournal -e sh -c 'echo hi > foo1; echo hi2 > foo2'
$ shournal -q --history 1
# ...
Written file(s):
/tmp/foo1 (3 bytes) Hash: 15349503233279147316
/tmp/foo2 (4 bytes) Hash: 2770363686119514911