2

有没有办法计算 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 */
 };

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

4

1 回答 1

2

有几个选项:

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

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

于 2013-02-14T18:13:48.273 回答