有没有办法计算 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 */
};
但是这里没有提供 fork 的数量。下一个想法是追踪 shell 和 child 并寻找 fork 。有没有更简单、开销更少的方法?是否有一些带有非标准选项/变量/机制的 shell 可以显示 fork 数量?
最佳答案
有几个选项:
- 最好的多平台方法可能是
strace
或其等效项(truss
、ktrace
)或dtrace
。见下文。这还允许您附加到正在运行的进程。 - 一种可行但稍微棘手的多平台方法是使用您自己的
fork/execve
版本创建动态库等等,记录调用,然后调用真正的 C 库函数。搜索LD_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 上,您可以通过以下方式跟踪执行情况(适度的性能损失):
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
允许您跟踪用户态库和内核系统调用。您还可以使用dtrace
,请参阅此处了解一些想法:http://www.brendangregg.com/DTrace/lostcpu.html
其他平台的变量类似于 LD_DEBUG
或LD_VERBOSE
,请参阅链接器文档(例如 man ld.so
)。
在上述情况下,您应该了解程序(通常)调用的是 C 库函数,例如fork()
,内核的请求至少取决于操作系统,并且可能会导致 vfork
的系统调用 , execve
或clone
.
关于shell - shell 脚本在执行期间执行的 fork 次数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14820869/