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 スクリプトを表示できますか?

このワンライナーは、実行中のプロセスの名前を出力します。

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

しかし、コマンドライン引数を取得/出力する方法は?

于 2009-01-20T01:21:44.023 に答える