shell脚本在执行期间执行的分叉数

时间:2013-02-11 21:07:34

标签: shell fork

有没有办法计算shell脚本在执行时执行的分叉数?我一直在寻找可能使用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 */
 };

但这里没有叉子数量。接下来的想法是将贝壳和儿童分开并寻找叉子。是否有更简单的方法,更少的开销?是否有一些带有非标准选项/变量/机制的shell来显示分叉数?

1 个答案:

答案 0 :(得分:2)

有几个选择:

  • 最佳的多平台方法可能是strace或等效(trussktrace)或dtrace。见下文。这也允许您附加到正在运行的进程。
  • 一个可行的,如果有点棘手的多平台方法是使用您自己的fork/execve等版本创建一个动态库,它记录调用,然后调用真正的C库函数。在SO上搜索LD_PRELOAD以获得一些想法。但这不适用于静态链接的二进制文件。
  • 在Linux和Solaris上,您可以设置环境变量LD_DEBUG=files,动态链接器将在加载可执行文件和库时发出各种诊断信息,这对于这么简单的步骤应该是有启发性的。在Linux上,每个新进程都应输出部分或大部分“initialize”,“init”和“fini”条目以及PID。但这不适用于静态链接的二进制文件。
  • 如果您使用的是Linux或* BSD或Solaris,并具有root访问权限,并且可以使用进程记帐,则可以运行命令,然后检查lastcommdump-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

Solaris truss允许您跟踪userland库和内核系统调用。您也可以使用dtrace,请点击此处查看一些提示:http://www.brendangregg.com/DTrace/lostcpu.html

其他平台的变量类似于LD_DEBUGLD_VERBOSE,请参阅链接器文档(例如man ld.so)。

在上述情况下,您应该了解哪些程序(通常)调用C库函数,例如fork(),内核请求的内容至少取决于操作系统,它可能会导致vforkexecve或{{1}的系统调用 }。