2

シェルスクリプトの実行中に実行されるフォークの数を計算する方法はありますか?getrusage(2)のさまざまなフィールドを使用して分析し、Cラッパーを作成することを検討してきました。

 struct rusage {
         struct timeval ru_utime; /* user time used */
         struct timeval ru_stime; /* system time used */
         long ru_maxrss;          /* max resident set size */
         long ru_ixrss;           /* integral shared text memory size */
         long ru_idrss;           /* integral unshared data size */
         long ru_isrss;           /* integral unshared stack size */
         long ru_minflt;          /* page reclaims */
         long ru_majflt;          /* page faults */
         long ru_nswap;           /* swaps */
         long ru_inblock;         /* block input operations */
         long ru_oublock;         /* block output operations */
         long ru_msgsnd;          /* messages sent */
         long ru_msgrcv;          /* messages received */
         long ru_nsignals;        /* signals received */
         long ru_nvcsw;           /* voluntary context switches */
         long ru_nivcsw;          /* involuntary context switches */
 };

ただし、フォークの数はここでは利用できません。次のアイデアは、シェルと子をstraceして、フォークを探すことです。オーバーヘッドが少ない、より簡単な方法はありますか?フォークの数を表示するための非標準のオプション/変数/メカニズムを備えたシェルはありますか?

4

1 に答える 1

2

いくつかのオプションがあります:

  • 最良のマルチプラットフォームアプローチは、可能性が高いstraceか、同等のもの(trussktrace)、またはdtraceです。下記参照。これにより、実行中のプロセスにアタッチすることもできます。
  • 実行可能な、少しトリッキーなマルチプラットフォームアプローチはfork/execve、呼び出しをログに記録し、実際のCライブラリ関数を呼び出す独自のバージョンのetcを使用してダイナミックライブラリを作成することです。SOを検索しLD_PRELOADて、いくつかのアイデアを入手してください。ただし、これは静的にリンクされたバイナリでは機能しません。
  • LinuxとSolarisでは、環境変数を設定できますLD_DEBUG=files。動的リンカーは、実行可能ファイルとライブラリの両方がロードされるときにさまざまな診断を発行します。このような単純な手順を理解する必要があります。Linuxでは、新しい各プロセスは、PIDとともに、「initialize」、「init」、および「fini」エントリの一部またはほとんどを出力する必要があります。ただし、これは静的にリンクされたバイナリでは機能しません。
  • Linux、* BSD、またはSolarisを使用していて、rootアクセス権があり、プロセスアカウンティングが使用可能な場合は、コマンドを実行してから、lastcommまたはの出力を検査できますdump-acct。これには、アカウンティングを開始する必要がある場合があります(まだ実行されていない場合)。これにより、一部のプラットフォームで必要な詳細が提供されない場合があります。これはRH/CentOS 6で簡単に実行でき、必要なすべての詳細を提供します。他のシステムにもプロセスアカウンティングがあります。
  • Linuxを使用していて、auditdサポートがある場合はautrace myscript.sh、システムコールをログに記録するために使用できます。(auditdカーネルデータが監査ファイルに記録されるように、このために実行する必要があります)
  • 完全を期すために:デバッガーを使用することもできますが、それは私が考えることができる最も退屈なアプローチです;-)

Linuxでは、次の方法で実行をトレースできます(中程度のパフォーマンスペナルティ)。

strace -f -o /tmp/myscript.trace -e trace=process ./myscript.sh

次に、ファイルを調べ.traceます。パラメータ-e trace=processは、プロセス関連のシステムコールのみを表示するようにフィルタリングします。

Solarisでは、次の方法でトレースできます。

truss -f -o /tmp/myscript.trace \
  -u libc:fork,execl,execv,execle,execve,execlp,execvp ./myscript.sh

Solaristrussでは、ユーザーランドライブラリとカーネルシステムコールの両方をトレースできます。を使用することもできます。dtraceいくつかのアイデアについては、こちらを参照してください:http ://www.brendangregg.com/DTrace/lostcpu.html

LD_DEBUG他のプラットフォームには、またはに類似した変数があります。LD_VERBOSEリンカーのドキュメントを参照してください(例man ld.so)。

上記の場合、(通常)呼び出すプログラムはCライブラリ関数であることを理解する必要があります。たとえばfork()、カーネルに要求されるものは少なくともOSに依存し、、、またはのsyscallが発生する可能性があります。vforkexecveclone

于 2013-02-14T18:13:48.273 に答える