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

shell脚本在执行期间执行的分叉数,shell,fork,Shell,Fork,有没有办法计算shell脚本在执行时执行的fork数?我一直在考虑使用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 */

有没有办法计算shell脚本在执行时执行的fork数?我一直在考虑使用
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
    或其等效物(
    truss
    ktrace
    ),或
    dtrace
    )。见下文。这还允许您附加到正在运行的进程
  • 一种可行的、尽管有点棘手的多平台方法是使用您自己版本的
    fork/execve
    等创建一个动态库,记录调用,然后调用真正的C库函数。搜索
    LD\u PRELOAD
    以获得一些想法。但这在静态链接的二进制文件上不起作用
  • 在Linux和Solaris上,您可以设置环境变量
    LD_DEBUG=files
    ,动态链接器将在加载可执行文件和库时发出各种诊断,这对于这样一个简单的步骤应该是有启发的。在Linux上,每个新进程都应该输出一些或大部分“initialize”、“init”和“fini”条目以及PID。但这在静态链接的二进制文件上不起作用
  • 如果您在Linux或*BSD或Solaris上,并且具有root访问权限,并且进程记帐可用,则可以运行命令,然后检查
    lastcomm
    dump acct
    的输出。这可能需要启动记帐(如果尚未运行)。这可能无法提供某些平台上所需的详细信息。它可以在RH/CentOS 6上轻松完成,并提供了所需的所有详细信息。其他系统也有过程会计
  • 如果您在Linux上并且拥有
    auditd
    支持,则可以使用
    autrace myscript.sh
    记录系统调用。(
    auditd
    应为此运行,以便将内核数据记录到审核文件)
  • 完整性:您可以使用调试器,但这是我能想到的最乏味的方法;-)
在Linux上,您可以通过以下方式跟踪执行(中等性能损失):

然后检查
.trace
文件。参数
-e trace=process
筛选只显示与流程相关的系统调用

在Solaris上,您可以通过以下方式进行跟踪:

truss -f -o /tmp/myscript.trace \
  -u libc:fork,execl,execv,execle,execve,execlp,execvp ./myscript.sh
Solaris
truss
允许您跟踪用户区库和内核系统调用。您也可以使用
dtrace
,有关一些想法,请参见此处:

其他平台的变量类似于
LD\u DEBUG
LD\u VERBOSE
,请参阅链接器文档(例如
man LD.so


在上述情况下,您应该了解程序(通常)调用的是C库函数,例如
fork()
,对内核的请求至少取决于操作系统,它可能导致系统调用
vfork
execve
clone
更简单,开销更小,这是一个很难解决的问题。您可以尝试插入一个非常简单的叉计数垫片。可能很快,可能不比strace简单。
truss -f -o /tmp/myscript.trace \
  -u libc:fork,execl,execv,execle,execve,execlp,execvp ./myscript.sh