web-dev-qa-db-ja.com

ストラップはどのように使うべきですか?

ある同僚がかつて私に、すべてがLinux上でデバッグに失敗したときの最後の選択肢は strace を使うことであると言った。

私はこの奇妙なツールの背後にある科学を学ぼうとしましたが、私はシステム管理者ではなく、本当に結果が得られませんでした。

そう、

  • それは正確には何ですか、それは何をしますか?
  • どのような場合にどのような場合に使用するべきですか?
  • 出力はどのように理解され処理されるべきですか?

簡単に言うと、という簡単な言葉で、これはどのように機能するのでしょうか。

256
e-satis

概要の概要
straceは軽量デバッガと見なすことができます。それはプログラマー/ユーザーがプログラムがOSとどのように相互作用しているかを素早く知ることを可能にします。システムコールとシグナルを監視することによってこれを行います。

使用方法
あなたがソースコードを持っていなかったり、本当にそれを通り抜けることに煩わされたくないときにはいいでしょう。
また、GDBをオープンにしたくないが、外部の対話を理解することだけに興味がある場合は、自分のコードに役立ちます。

ちょっとした紹介
私はこのイントロで先日だけ使用するために使用しました。 strace hello world

178
John Mulder

簡単に言うと、straceはプログラムによって発行されたすべてのシステムコールとその戻りコードをトレースします。ファイル/ソケット操作など、もっと曖昧なものを考えてください。

ここでシステムコールはより正確に標準Cライブラリコールを表しているので、あなたがCについてある程度の実用的な知識を持っているなら、それは最も役に立ちます。

あなたのプログラムが/ usr/local/bin/coughだとしましょう。単に使用する:

strace /usr/local/bin/cough <any required argument for cough here>

または

strace -o <out_file> /usr/local/bin/cough <any required argument for cough here>

'out_file'に書き込む。

すべてのstraceの出力は標準エラー出力に送られます(注意してください、それの莫大な量はしばしばファイルへのリダイレクトを要求します)。最も単純なケースでは、あなたのプログラムはエラーで中止され、そしてあなたがその最後にOSとのやりとりをどこで行っているのかを見ることができるでしょう。

より多くの情報が利用可能であるべきです:

man strace
60
bltxd

straceは、それが適用されるプロセスによって行われたすべてのシステムコールをリストします。システムコールが何を意味するのかわからなければ、そこから多くのマイレージを得ることはできません。

それでも、問題にファイルやパス、環境値が含まれる場合は、問題のあるプログラムでstraceを実行し、出力をファイルにリダイレクトしてから、そのファイルをpath/file/env文字列に変換すると、あなたがそれを期待したものとは異なるように、実際にをやろうとしています。

34
Asaf Bartov

私はアクセス権の問題をデバッグするためにずっとstraceを使います。手法は次のようになります。

$ strace -e trace=open,stat,read,write gnome-calculator

gnome-calculatorは実行したいコマンドです。

15
Jeff Sheffield

Straceは、デバッガの下でこれらのプログラムを実行することができないような運用システムを調査するためのツールとして際立っています。特に、次の2つの状況でstraceを使用しました。

  • プログラムfooがデッドロック状態になり、応答しなくなりました。これはgdbのターゲットになる可能性があります。しかし、私たちは常にソースコードを持っているわけではなく、デバッガのもとで実行するのが簡単ではないスクリプト言語を扱うこともありました。この場合、既に実行中のプログラムでstraceを実行すると、行われているシステムコールのリストが表示されます。これは、クライアント/サーバーアプリケーションまたはデータベースと対話するアプリケーションを調査している場合に特に役立ちます。
  • プログラムが遅い理由を調べる特に、新しい分散ファイルシステムに移行したばかりで、システムの新しいスループットは非常に遅くなりました。各システムコールにどれだけの時間が費やされたかを示す '-T'オプションでstraceを指定することができます。これは、ファイルシステムが原因で速度が低下している原因を特定するのに役立ちました。

Straceを使用した分析の例については、 この質問 に対する私の回答を参照してください。

15
terson

strace -tfp PIDはPIDプロセスのシステムコールを監視するので、プロセス/プログラムの状態をデバッグ/監視することができます。

7
Leslie Zhu

Straceはデバッグツールとして、またはプリミティブプロファイラーとして使用できます。

デバッガとして、与えられたシステムコールがどのように呼び出され、実行され、それらが何を返すのかを見ることができます。プログラムが失敗したことだけでなく、プログラムが失敗した理由もわかるので、これは非常に重要です。通常、これは単純なコーディングがプログラムのすべての可能な結果を​​捕捉できないことによるものです。それ以外の場合は、ファイルへのパスをハードコードするだけです。緊張がなければ、どこでどのように問題が発生したのかを推測できます。 straceを使用すると、システムコールの内訳が表示されます。通常、戻り値を見るだけで多くのことがわかります。

プロファイリングは別の用途です。これを使用して、各システムコールの実行を個別に、または集計として時間設定することができます。これでは問題を解決するのに十分ではないかもしれませんが、少なくとも潜在的な容疑者のリストは大幅に絞り込まれます。 1つのファイルに多くのfopen/closeペアがある場合は、ループの外側で開閉するのではなく、ループを実行するたびに不必要にファイルを開閉します。

Ltraceは、straceの親しいいとこでもあり、とても役に立ちます。あなたはあなたのボトルネックがどこにあるかを区別することを学ぶ必要があります。合計実行時間が8秒で、システムコールに0.05秒しか費やさない場合、プログラムをトレースしてもそれほどうまくいかない、問題はコード内にある、通常はロジックの問題、またはプログラムで実際に必要な問題実行に時間がかかる。

Strace/ltraceの最大の問題はそれらの出力を読むことです。どのようにして呼び出しが行われたのか、あるいは少なくともsyscalls/functionsの名前がわからなければ、その意味を理解するのは困難になるでしょう。関数が何を返すのかを知ることは、特に異なるエラーコードにとって非常に有益です。解読するのは大変ですが、真珠の知識を返すこともあります。 iノードが不足しても空き容量が不足していないという状況が発生したため、通常のユーティリティでは警告が表示されず、新しいファイルを作成できませんでした。 straceの出力からエラーコードを読むと正しい方向に向いていました。

6
Marcin

straceは、プログラムがさまざまなシステムコール(カーネルへの要求)をどのようにして行うのかを学ぶための優れたツールであり、その失敗に関連するエラー値とともに失敗したものも報告します。すべての失敗がバグであるとは限りません。たとえば、ファイルを検索しようとしているコードはENOENT(そのようなファイルまたはディレクトリはありません)エラーを受け取る可能性がありますが、それはコードのロジックにおける許容可能なシナリオである可能性があります。

Straceを使用する良い使用例の1つは、一時ファイル作成中に競合状態をデバッグすることです。たとえば、プロセスID(PID)をあらかじめ決められた文字列に追加することによってファイルを作成している可能性があるプログラムは、マルチスレッドのシナリオで問題に直面する可能性があります。 [PID + TID(プロセスID +スレッドID)、またはmkstempなどのより良いシステムコールでこれが解決されます]。

クラッシュのデバッグにも役立ちます。あなたは straceとデバッグのクラッシュに関するこの(私の)記事 が役に立つかもしれません。

4
mohit

Straceは、アプリケーションがオペレーティングシステムとどのように相互作用するかを説明するツールです。

これは、アプリケーションが使用するOSシステム呼び出しと、それらを呼び出すパラメーターを指定することによって行われます。

たとえば、プログラムがどのファイルを開こうとしているのかがわかり、呼び出しが成功するのです。

このツールを使えば、あらゆる種類の問題をデバッグできます。例えば、あなたがインストールしたことをあなたが知っているライブラリを見つけることができないとアプリケーションが言うならば、あなたはstraceがアプリケーションがそのファイルを探している場所をあなたに教えるでしょう。

そしてそれは氷山の一角にすぎません。

4
Luka Marinko

最小実行可能例

概念が明確ではない場合は、それを説明する見たことのない簡単な例があります。

この場合、その例はLinux x86_64アセンブリ自立型(libcなし)のHello Worldです。

こんにちは。

.text
.global _start
_start:
    /* write */
    mov $1, %rax    /* syscall number */
    mov $1, %rdi    /* stdout */
    mov $msg, %rsi  /* buffer */
    mov $len, %rdx  /* buffer len */
    syscall

    /* exit */
    mov $60, %rax   /* exit status */
    mov $0, %rdi    /* syscall number */
    syscall
msg:
    .ascii "hello\n"
len = . - msg

GitHubアップストリーム

組み立てて実行します。

as -o hello.o hello.S
ld -o hello.out hello.o
./hello.out

期待どおりに出力します。

hello

それでは、その例でstraceを使用しましょう。

env -i ASDF=qwer strace -o strace.log -s999 -v ./hello.out arg0 arg1
cat strace.log

を使用しております:

strace.logに含まれるもの:

execve("./hello.out", ["./hello.out", "arg0", "arg1"], ["ASDF=qwer"]) = 0
write(1, "hello\n", 6)                  = 6
exit(0)                                 = ?
+++ exited with 0 +++

このような最小限の例では、出力のすべての1文字は自明です。

  • execve行:stracehello.outをどのように実行したかを示します。man execveに記載されているCLI引数および環境も含まれます。

  • write行:行ったwriteシステムコールを示します。 6は、ストリング"hello\n"の長さです。

    = 6はシステムコールの戻り値で、man 2 writeに記載されているように書き込まれたバイト数です。

  • exit行:行ったexitシステムコールを示します。プログラムが終了したため、戻り値はありません。

より複雑な例

Straceの応用はもちろんあなたのプログラムをデバッグ/最適化するのを助けるためにどのシステムコールが複雑なプログラムを実際にしているかを見ることです。

特に、Linuxで遭遇する可能性があるほとんどのシステムコールはglibcラッパーを持っています。 それらの多くはPOSIX からのものです。

内部的には、glibcラッパーはほぼ次のようにインラインアセンブリを使用します。 インラインアセンブリでsysenterを介してシステムコールを呼び出す方法?

次に学ぶべき例はPOSIXのwriteこんにちは世界です。

main.c

#define _XOPEN_SOURCE 700
#include <unistd.h>

int main(void) {
    char *msg = "hello\n";
    write(1, msg, 6);
    return 0;
}

コンパイルして実行します。

gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out

今回は、mainの前にglibcによってたくさんのシステムコールが行われ、main用にNice環境がセットアップされることがわかります。

これは、私たちが現在自立型のプログラムを使用しているのではなく、libc機能を可能にする、より一般的なglibcプログラムを使用しているためです。

そして、最後にstrace.logには以下が含まれます。

write(1, "hello\n", 6)                  = 6
exit_group(0)                           = ?
+++ exited with 0 +++

したがって、write POSIX関数はLinuxのwriteシステムコールを使用しています。

return 0exitではなくexit_group呼び出しにつながることも確認しました。ハ、私はこれについて知りませんでした!これがstraceがとてもクールな理由です。 man exit_groupは次に説明します。

このシステムコールは、呼び出し側スレッドだけでなく、呼び出し側プロセスのスレッドグループ内のすべてのスレッドも終了させることを除いて、exit(2)と同じです。

dlopenがどのシステムコールを使用するかを調べた別の例を次に示します。 https://unix.stackexchange.com/questions/226524/what-system-call-is-used-to-load-libraries -in-linux/462710#462710

Ubuntu 16.04、GCC 6.4.0、Linuxカーネル4.4.0でテスト済み。

私はstraceがあなたがあなたのオペレーティングシステムとどのようにやり取りするかをチェックするという答えのいくつかが好きでした。

これはまさに私たちが見ることができるものです。システムコールstraceltraceを比較すると、違いはより明白です。

$>strace -c cd
Desktop  Documents  Downloads  examples.desktop  Music  Pictures  Public  Templates  Videos
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0         7           read
  0.00    0.000000           0         1           write
  0.00    0.000000           0        11           close
  0.00    0.000000           0        10           fstat
  0.00    0.000000           0        17           mmap
  0.00    0.000000           0        12           mprotect
  0.00    0.000000           0         1           munmap
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         2           rt_sigaction
  0.00    0.000000           0         1           rt_sigprocmask
  0.00    0.000000           0         2           ioctl
  0.00    0.000000           0         8         8 access
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         2           getdents
  0.00    0.000000           0         2         2 statfs
  0.00    0.000000           0         1           Arch_prctl
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0         9           openat
  0.00    0.000000           0         1           set_robust_list
  0.00    0.000000           0         1           prlimit64
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                    93        10 total

一方、関数をトレースするltraceがあります。

$>ltrace -c cd
Desktop  Documents  Downloads  examples.desktop  Music  Pictures  Public  Templates  Videos
% time     seconds  usecs/call     calls      function
------ ----------- ----------- --------- --------------------
 15.52    0.004946         329        15 memcpy
 13.34    0.004249          94        45 __ctype_get_mb_cur_max
 12.87    0.004099        2049         2 fclose
 12.12    0.003861          83        46 strlen
 10.96    0.003491         109        32 __errno_location
 10.37    0.003303         117        28 readdir
  8.41    0.002679         133        20 strcoll
  5.62    0.001791         111        16 __overflow
  3.24    0.001032         114         9 fwrite_unlocked
  1.26    0.000400         100         4 __freading
  1.17    0.000372          41         9 getenv
  0.70    0.000222         111         2 fflush
  0.67    0.000214         107         2 __fpending
  0.64    0.000203         101         2 fileno
  0.62    0.000196         196         1 closedir
  0.43    0.000138         138         1 setlocale
  0.36    0.000114         114         1 _setjmp
  0.31    0.000098          98         1 realloc
  0.25    0.000080          80         1 bindtextdomain
  0.21    0.000068          68         1 opendir
  0.19    0.000062          62         1 strrchr
  0.18    0.000056          56         1 isatty
  0.16    0.000051          51         1 ioctl
  0.15    0.000047          47         1 getopt_long
  0.14    0.000045          45         1 textdomain
  0.13    0.000042          42         1 __cxa_atexit
------ ----------- ----------- --------- --------------------
100.00    0.031859                   244 total

マニュアルを何度かチェックしましたが、straceという名前のOriginは見つかりませんでしたが、これは明らかなので、おそらくシステムコールのトレースです。

straceについて、3つの大きな注意点があります。

注意1:これらの関数straceltraceはどちらもシステムコール ptrace を使用しています。そのため、ptraceシステムコールは実質的にstraceの機能のしくみです。

Ptrace()システムコールは、あるプロセス(「トレーサ」)が別のプロセス(「トレース」)の実行を監視および制御し、トレースのメモリとレジスタを調べて変更するための手段を提供します。主にブレークポイントデバッグとシステムコールトレースの実装に使用されます。

注2:straceは非常に冗長になる可能性があるため、straceで使用できるさまざまなパラメータがあります。私は-cを試してみるのが好きです。これは物事の要約のようなものです。 -cに基づいて、-e trace=openのようなシステムコールを1つ選択することができます。そこではそのコールだけが表示されます。あなたがトレースしているコマンドの間にどんなファイルが開かれるかを調べているならば、これは面白いことができます。もちろん、grepを同じ目的で使用することもできますが、コマンドが発行されたときに設定ファイルが参照されることを理解するために、この2>&1 | grep etcのようにリダイレクトする必要があることに注意してください。

注3:私はこの非常に重要な注釈を見つけました。あなたは特定のアーキテクチャに制限されていません。 straceは、異なるアーキテクチャのバイナリをトレースすることができるので、気にしないでください。 enter image description here

1
prosti