web-dev-qa-db-ja.com

失敗したsyscallをstraceログから除外する

stracesleep 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'以外に、失敗した呼び出しを確実に除外するにはどうすればよいですか?

4

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プロセスによって正常に開かれたファイルの名前が表示されます。

4
Stephen Kitt

可能な解決策:

strace -e trace=file sleep 1 2>&1 | grep -v "= -1 ENOENT" > strace.log

straceはデフォルトでstderrに出力されるため、stdoutにリダイレクトします。

1
Yurij Goncharuk

少し信頼性の高いパターン(つまり、誤って間違った行をスキップするリスクが少し少ない)は、

| 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

1
sourcejedi