4

有一些 Mac GUI 应用程序为更令人讨厌的命令行工具(通常包含在应用程序包的一部分)提供前端。我想看看这些 GUI 背后发生了什么。

如何“附加”到应用程序,监视它是否调用命令行实用程序并记录这些调用的文件名和命令行参数?

解决方案也可以是记录 Mac OS X 上所有应用程序执行的应用程序(过滤掉最常见的系统调用)。

示例 GUI 前端: http: //xact.sourceforge.net/(因为它是开源的,所以可以调试它,但 xACT 只是一个示例。假设我们只有一个现成的 *.app 来监控)。

更新: dtrace 可以监视 exec 调用并打印调用的命令的名称。这是解决方案的一半,另一半是获取它的命令行参数。这还没有解决(直到有人确认他们有 dtrace 来做这件事)。

4

4 回答 4

6

DTrace 可以完成这项工作。根据我在此问题其他地方的评论中与 Joey Hagedorn 的讨论,可以改进 10.6 附带的脚本以使用合理数量的参数(50+)。因为该脚本有很多重复,我将在此处包含一个脚本,该脚本输出运行良好的 DTrace 脚本。这个最多可以处理 50 个参数;您可能希望通过更改 for 循环来扩展参数的数量。

#!/bin/bash

cat <<HEADER
#!/usr/sbin/dtrace -s
/*
 * newproc.d - snoop new processes as they are executed. DTrace OneLiner.
 *
 * This is a DTrace OneLiner from the DTraceToolkit.
 *
 * 15-May-2005  Brendan Gregg   Created this.
 */

/*
 * Updated to capture arguments in OS X. Unfortunately this isn't straight forward...
 */

#pragma D option quiet

this unsigned long long argv_ptr; /* Wide enough for 64 bit user procs */

proc:::exec-success
{
    print_pid[pid] = 1; /* This pid emerged from an exec, make a note of that. */
}

/*
 * The "this" variables are local to (all) of the following syscall::mmap:return probes,
 * and only those probes. They must be initialized before use in each new firing.
 */
syscall::mmap:return
{
    this->argc = 0; /* Disable argument collection until we notice an exec-success */
}

syscall::mmap:return
/ print_pid[pid] /
{
    print_pid[pid] = 0;

    this->is64Bit = curpsinfo->pr_dmodel == PR_MODEL_ILP32 ? 0 : 1;
    this->wordsize = this->is64Bit ? 8 : 4;

    this->argc = curpsinfo->pr_argc; 
    this->argc = (this->argc < 0) ? 0 : this->argc; /* Safety */

    this->argv_ptr = curpsinfo->pr_argv;

    printf("%d %s ", pid, this->is64Bit ? "64b" : "32b");
}

HEADER

for ((i=0;i<50;++i)); do

cat <<REPEAT
syscall::mmap:return
/ this->argc /
{
    this->here_argv = copyin(this->argv_ptr, this->wordsize);
    this->arg = this->is64Bit ? *(unsigned long long*)(this->here_argv) : *(unsigned long*)(this->here_argv);
    printf("%s ", copyinstr(this->arg));
    this->argv_ptr += this->wordsize;
    this->argc--;
}

REPEAT
done

cat <<FOOTER
syscall::mmap:return
/ this->argv_ptr /
{
    printf("%s\n", this->argc > 0 ? "(...)" : "");
    this->argc = 0;
    this->argv_ptr = 0;
}
FOOTER
于 2010-10-11T19:07:10.047 回答
5

newproc.d是另一个 dtrace 脚本,也将进程的命令行参数输出到进程名称。运行它很简单:

sudo newproc.d

这适用于我在 OS X Mountain Lion 上。旧版本可能存在各种问题;有关 Leopard 和 Snow Leopard 上 newproc.d 的一些讨论,请参阅此ServerFault 答案的评论线程。

此外,您应该注意一些小的限制。如果你看一下脚本的源代码,它表明它不会显示超过 5 个参数,并且不会显示长度超过 128 个字符的参数:

/*
 * Updated to capture arguments in OS X. Unfortunately this isn't straight forward... nor inexpensive ...
 * Bound the size of copyinstr()'s and printf incrementally to prevent "out of scratch space errors"
 * print "(...)" if the length of an argument exceeds COPYINSTRLIMIT.
 * print "<...>" if argc exceeds 5.
 */

inline int COPYINSTRLIMIT = 128;
于 2013-01-26T21:16:18.430 回答
3

您可以使用 dtrace 监视 exec*() 系统调用并在调用它们时显示参数。dtrace 记录在这里: https ://wikis.oracle.com/display/DTrace/Documentation

于 2009-01-19T22:47:55.520 回答
2

Graham:dtrace 在这里会很完美。您(或这里的任何其他人)能否显示一个打印进程命令行的 dtrace 脚本?

这个 oneliner 打印正在执行的进程的名称:

dtrace -qn 'syscall::exec*:return { printf("%Y %s\n",walltimestamp,curpsinfo->pr_psargs); }' 

但是如何获取/打印他们的命令行参数呢?

于 2009-01-20T01:21:44.023 回答