2013-02-11 71 views
2

有没有一种方法可以计算shell脚本在执行时执行的分支数?我一直在看,也许写的用getrusage(2)一个C包装和分析shell脚本在执行过程中执行的分支数

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来显示分叉数量?

+0

更简单和更少的开销是一个艰难的行锄。你可以尝试插入一个非常简单的叉子计数垫片。可能很快,可能并不比strace简单。 – 2013-02-11 22:27:00

回答

2

有几个选项:

  • 最好的多平台方式可能strace或同等学历(trussktrace),或dtrace。见下文。这也可以让你连接到正在运行的进程。
  • 一个可行的,如果有点棘手的多平台方法是创建一个动态库与你自己的版本fork/execve等,它记录了调用,然后调用真正的C库函数。搜索如果LD_PRELOAD得到一些想法。尽管如此,这对静态链接的二进制文件不起作用。
  • 在Linux和Solaris上,您可以设置环境变量LD_DEBUG=files,并且动态链接器将在加载可执行文件和库时发出各种诊断信息,因此对于这样一个简单的步骤应该具有启发性。在Linux上,每个新进程应输出一些或大部分“初始化”,“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器,可以跟踪用户区库和内核系统调用。你也可以使用dtrace,看到这里的一些想法:http://www.brendangregg.com/DTrace/lostcpu.html

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

在上述情况下,您应该了解哪些程序(通常)会调用C库函数,例如fork(),所要求的内核至少取决于OS,并且可能导致系统调用vforkexecveclone