strace
をsleep 1
のようなコマンドで実行すると、次のように、アクセスしているファイルを確認できます。
strace -e trace=file -o strace.log sleep 1
ただし、私のマシンでは、多くの呼び出しの戻り値が-1で、ファイルが存在しないことを示しています。例えば:
$ grep '= -1 ENOENT' strace.log | head
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_MEASUREMENT", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_TELEPHONE", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_ADDRESS", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_NAME", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_PAPER", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
存在しないファイルにはあまり興味がありません。プロセスが実際に見つけて読み取ったファイルを知りたいのですが。 grep -v '=-1 ENOENT'
以外に、失敗した呼び出しを確実に除外するにはどうすればよいですか?
strace
出力の後処理を除いて、strace
で失敗したシステムコールを無視するために利用できるものはありません。追加するのはそれほど難しくありません。syscall_exiting_trace
関数 syscall.c
。
後処理の角度を追求したい場合は、 Ole Tange が、ここに到達する可能性が高いよりも包括的な方法ですでに対処しています。 tracefile
ツールはstrace
を実行し、読みやすい方法で必要な情報を除外します。詳細は プログラムがアクセスするファイルのリスト を参照してください。 別の答え その質問に対する他の可能なアプローチのリスト LoggedFS を含めて、これは非常に便利だと思います。
別のオプションは SystemTap を使用することです。例えば
#!/usr/bin/env stap
global stored_filename, stored_path
probe syscall.open {
stored_filename = filename
}
probe syscall.open.return {
if (execname() == "cat" && $return >= 0) {
printf("opened %s\n", stored_filename)
}
}
probe syscall.openat {
stored_filename = filename
stored_path = dfd_str
}
probe syscall.openat.return {
if (execname() == "cat" && $return >= 0) {
printf("opened %s in %s\n", stored_filename, stored_path)
}
}
cat
プロセスによって正常に開かれたファイルの名前が表示されます。
可能な解決策:
strace -e trace=file sleep 1 2>&1 | grep -v "= -1 ENOENT" > strace.log
strace
はデフォルトでstderr
に出力されるため、stdout
にリダイレクトします。
少し信頼性の高いパターン(つまり、誤って間違った行をスキップするリスクが少し少ない)は、
| grep -v "= -1 ENOENT [(]No such file or directory[)]$"
つまり行の終わりをコピーアンドペーストし、角かっこをエスケープします(そうしないと特殊文字として扱われる可能性があります)。また、特殊文字$
を末尾に追加して、パターンを行の末尾に「固定」します。
man strace
にはこれ以上のオプションはありません。素早い汚いテキスト操作ハックは、Unix Way :-Pです。
カスタムgdb
スクリプトを使用して、希望どおりの操作を行うことはほぼ確実に可能です。しかし、それはより多くの作業であり、私はそのようなスクリプトを準備していません。
別の質問はtracefile
スクリプトを参照しており、-e
オプションを指定して実行します。これはstrace
の出力を解析することでまだ実装されているため、完全に信頼できるとは言えませんが、好みの可能性はあると思います。 https://gitlab.com/ole.tange/tangetools/blob/master/tracefile/tracefile