Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macos 如何从一开始就跟踪一个程序,而不将其作为根运行_Macos_Dtrace - Fatal编程技术网

Macos 如何从一开始就跟踪一个程序,而不将其作为根运行

Macos 如何从一开始就跟踪一个程序,而不将其作为根运行,macos,dtrace,Macos,Dtrace,我正在编写一个工具,通过调用DTrace来跟踪用户指定的程序 如果我的工具使用dtrace-c作为dtrace的子进程运行程序,那么我不仅不能向程序传递任何参数,而且程序以dtrace的所有权限(即root权限)运行(我在Mac OS X上)。这使得某些应该工作的事情中断,并且显然使许多不应该工作的事情成为可能 我知道的另一个解决方案是自己启动程序,通过发送它来暂停它,将它的PID传递到dtrace-p,然后通过发送它来继续它。问题是,在DTrace收集符号信息时,程序运行了几秒钟而没有被跟踪,

我正在编写一个工具,通过调用DTrace来跟踪用户指定的程序

如果我的工具使用dtrace-c作为dtrace的子进程运行程序,那么我不仅不能向程序传递任何参数,而且程序以dtrace的所有权限(即root权限)运行(我在Mac OS X上)。这使得某些应该工作的事情中断,并且显然使许多不应该工作的事情成为可能

我知道的另一个解决方案是自己启动程序,通过发送它来暂停它,将它的PID传递到dtrace-p,然后通过发送它来继续它。问题是,在DTrace收集符号信息时,程序运行了几秒钟而没有被跟踪,或者,如果我在继续该过程之前休眠了几秒钟,DTrace会抱怨
objc:::entry
与任何探测都不匹配


有没有一种方法可以让我在用户帐户下运行程序,而不是以root用户身份运行,但DTrace仍然能够从一开始就跟踪它?

创建一个启动程序,它将等待某种信号(不一定是文字信号,只是指示它已准备就绪),然后执行目标。现在,dtrace-p启动程序,一旦dtrace启动,让启动程序启动。

如果另一个答案对您不起作用,您可以在gdb中运行程序,中断main(甚至更早),获取pid并启动脚本吗?我过去试过,它似乎很管用。

类似于
sudo dtruss-f sudo-u
的东西对我很管用,但后来我觉得很糟糕


我提出了一个关于它的雷达错误,并将它作为#5108629的副本关闭。

好吧,这有点旧,但为什么不:-)

我不认为有一种方法可以简单地从命令行实现这一点,但正如所建议的,一个简单的启动程序应用程序,如下面所示,可以实现这一点。当然,手动附加也可以用几个对libdtrace的调用来代替

int main(int argc, char *argv[]) {
    pid_t pid = fork();
    if(pid == 0) {
        setuid(123);
        seteuid(123);
        ptrace(PT_TRACE_ME, 0, NULL, 0);
        execl("/bin/ls", "/bin/ls", NULL);
    } else if(pid > 0) {
        int status;
        wait(&status);

        printf("Process %d started. Attach now, and click enter.\n", pid);
        getchar();

        ptrace(PT_CONTINUE, pid, (caddr_t) 1, 0);
    }

    return 0;
}

此脚本将要监视到DTrace的可执行文件(对于应用程序,这是info.plist的CbundleExecutable)的名称作为参数(然后,您可以在运行此脚本后启动目标应用程序):

string gTarget;/*目标可执行文件的名称*/
dtrace:::开始
{
gTarget=$$1;/*从第一个DTrace参数获取目标execname*/
/*
*注意:DTrace的execname限制为15个字符,因此如果$$1有更多字符
*超过15个字符的简单字符串比较“($$1==execname)”
*将失败。我们通过复制$$1中传递的参数来解决此问题
*到gTarget并将其截断为15个字符。
*/
gTarget[15]=0;/*截断为15字节*/
gTargetPID=-1;/*使目标pid无效*/
}
/*
*捕获目标发射(成功)
*/
proc:::执行成功
/
gTarget==execname
/
{
gTargetPID=pid;
}
/*
*检测目标何时退出
*/
系统调用::*退出:进入
/
pid==gTargetPID
/
{
gTargetPID=-1;/*使目标pid无效*/
}
/*
*捕获开放参数
*/
syscall::open*:条目
/
((pid==gTargetPID)|子代(gTargetPID))
/
{
self->arg0=arg0;
self->arg1=arg1;
}
/*
*轨道开放
*/
syscall::open*:返回
/
((pid==gTargetPID)|子代(gTargetPID))
/
{
此->操作种类=((self->arg1&O_ACCMODE)=O_RDONLY)?“读取”:“写入”;
此->路径0=self->arg0?复制工具(self->arg0):“”;
printf(“为%s打开:#%d”,
这类,
这个->路径0,
arg0);
}

dtruss有
-n
选项,您可以在其中指定要跟踪的进程名称,而无需启动它(请参见@kenorb回答的后面部分)。因此,类似于以下内容的内容应该可以做到这一点:

sudo dtruss -n "$program"
$program
请参阅相关的“如何让dtrace以非根权限运行跟踪命令?”[sic]

基本上,您可以启动一个(非根)后台进程,该进程等待1秒DTrace启动(很抱歉出现争用情况),然后窥探该进程的PID

sudo-true&&\
(睡眠1;cat/etc/hosts)和\
sudo dtrace-n'syscall:::entry/pid=$1/{@[probefunc]=count();}'$\
&&杀死美元!

链接答案中的完整解释。

更好的是:将所有内容合并在一起。创建一个管道,fork,让孩子在管道上等待,dtrace-p child_PID,写入管道,孩子醒来并调用exec。不过,我不知道它是否会起作用:我的工具是用Python编写的,它是为跟踪Cocoa程序而设计的。如果我的工具中没有任何Cocoa,我想我仍然会得到一个错误,即objc提供程序不匹配任何探测。但我明天会试试。这很好,只是在执行此dtrace时没有找到任何pid提供程序跟踪点。例如,我得到一个错误:“探测描述pid*::confstr:return与任何探测都不匹配”
sudo dtruss -n "$program"
$program