Macos pid提供程序匹配在dtrace中来来去去去的进程

Macos pid提供程序匹配在dtrace中来来去去去的进程,macos,dtrace,Macos,Dtrace,我希望跟踪进程中给定库的所有函数调用,但进程将定期退出并重新打开,我希望继续跟踪 我现在正在这样做: oneshot$target:LIBRARY::entry { printf("%s\n", probefunc); } 但是,这只允许我一次提供一个pid。我能继续吗 我想要像这样的东西: *:LIBRARY::entry /execname == "foo"/ 但这在那里不起作用 谢谢 我认为单凭一个dtrace脚本是无法做到这一点的。你需要两个(至少…)。您需要能够运行破坏性的

我希望跟踪进程中给定库的所有函数调用,但进程将定期退出并重新打开,我希望继续跟踪

我现在正在这样做:

oneshot$target:LIBRARY::entry
{
    printf("%s\n", probefunc);
}
但是,这只允许我一次提供一个pid。我能继续吗

我想要像这样的东西:

*:LIBRARY::entry
/execname == "foo"/
但这在那里不起作用


谢谢

我认为单凭一个dtrace脚本是无法做到这一点的。你需要两个(至少…)。您需要能够运行破坏性的
system()
操作,这很可能意味着
root
访问

假设您希望在任何新的
ls
进程上运行此脚本:

#!/usr/sbin/dtrace -s

pid$1:libc::entry
{
    printf( "func: %s\n", probefunc );
}
假设该脚本的路径为
/root/dtrace/tracelibc.d
,则以下脚本将在启动的任何新
ls
进程上启动
dtrace
。请注意,您需要
#pragma D option
才能在新流程上启动
dtrace

#!/usr/sbin/dtrace -s

#pragma D option destructive
#pragma D option quiet

proc:::exec-success
/ "ls" == basename( execname ) /
{
    printf( "tracing process %d\n", pid );
    system( "/root/dtrace/tracelibc.d %d", pid );
}
这应该是可行的,但在这种情况下,
ls
是一个非常短暂的过程,类似的事情经常发生:

dtrace: failed to compile script /root/dtrace/tracelibc.d: line 10:
    failed to grab process 12289
dtrace
开始运行时,该过程已经结束。如果您正在跟踪长期存在的进程,并且不介意由于
dtrace
需要一段时间才能连接而错过前几个探测,那么就完成了

但是,如果要跟踪短期流程,则需要在流程启动时立即停止流程,然后在
dtrace
附加后重新启动流程:

#!/usr/sbin/dtrace -s

#pragma D option destructive
#pragma D option quiet

proc:::exec-success
/ "ls" == basename( execname ) /
{
    printf( "stopping process %d\n", pid );
    system( "/root/dtrace/tracelibc.d %d", pid );
    stop();
}
并在
tracelibc.d
中启动它:

#!/usr/sbin/dtrace -s

#pragma D option destructive

BEGIN
{
    system( "prun %d", $1 );
}

pid$1:libc::entry
{
    printf( "func: %s\n", probefunc );
}
请注意,我正在使用Solaris
prun
重新启动已停止的进程。您必须查看Mac
dtrace
文档中的
stop()
调用,才能获得与Solaris
prun
相当的Mac

但是。。。哎呀。上述两个脚本组合生成:

stopping process 12274
dtrace: failed to compile script /root/dtrace/tracelibc.d: line 10:
    probe description pid12274:libc::entry does not match any probes
为什么说
pid12274:libc::entry
与任何探测都不匹配?哦,是的-当
exec
返回时,
libc.so
共享对象还没有加载到内存中。我们需要一个保证存在于目标进程中的探测,它在
libc之后被调用。因此
被加载,但在任何处理完成之前
main
就足够了。因此,开始这一切的主脚本变成:

#!/usr/sbin/dtrace -s

#pragma D option destructive
#pragma D option quiet

proc:::exec-success
/ "ls" == basename( execname ) /
{
    printf( "stopping process %d\n", pid );
    system( "/root/dtrace/tracemain.d %d", pid );
    stop();
}
启动
tracemain.d
脚本,重新启动进程,加载
tracelibc.d
脚本,然后再次停止进程:

#!/usr/sbin/dtrace -s

#pragma D option destructive
#pragma D option quiet

BEGIN
{
    system( "prun %d", $1 );
}

pid$1::main:entry
{
    system( "/root/dtrace/tracelibc.d %d", $1 );
    stop();
    /* this instance of dtrace is now done */
    exit( 0 );
}
并且
tracelibc.d
添加了自己的
系统(“prun%d”,1美元)开始
探测中的code>,它看起来像:

#!/usr/sbin/dtrace -s

#pragma D option destructive

BEGIN
{
    system( "prun %d", $1 );
}

pid$1:libc::entry
{
    printf( "func: %s\n", probefunc );
}
这三种方法确实减慢了
ls
过程,但它们确实产生了预期的输出——正如预期的那样,有很多