Go to main content

手册页部分 1:用户命令

退出打印视图

更新时间: 2022年7月27日 星期三
 
 

truss(1)

名称

truss - 跟踪系统调用和信号

用法概要

truss [-fcaeilAdDEGIN] [-d]  [-D]  [-E]  [-G] [- [tTvx] [!] 
syscall ,...] 
      [- [sS] [!] signal ,...] [
- [mM] [!] fault ,...] 
      [- [rw] [!] fd ,...] 
      [- [uU] [!] lib ,... : [:] [!] 
func ,...] 
      [-o outfile] command
 | -p pid[
/lwps]...

描述

truss 实用程序执行指定的命令并跟踪记录其执行的系统调用、其收到的信号以及其引发的计算机故障。跟踪输出的每一行都会报告故障或信号名称,或者系统调用名及其参数和返回值。如果可以,将使用相关系统头中的定义通过符号方式显示系统调用参数。对于任何路径名指针参数,将显示指向字符串。使用 Intro(3) 中介绍的错误代码名称报告返回的错误。在出错情况下,如果内核报告缺少特权,则在错误代码名称后在方括号 ([ ]) 中报告privileges(7) 中介绍的特权名称。有关错误报告的更多信息,请参见“附注”部分。

某些情况下(请参见 –u 选项),truss 还将记录由受跟踪进程执行的用户级函数调用的进入/退出,以缩进形式表示嵌套。

选项

对于具有列表参数的选项,名称 all 可用作指定列表所有可能成员的快速方法。如果列表以 ! 开头,则该选项的含义是否定的(如,排除而不是跟踪)。可以指定同一选项多次出现。对于列表中的相同名称,后续选项(右侧选项)将覆盖之前的选项(左侧选项)。

支持以下选项:

–a

显示在各个 exec()spawn() 系统调用中传递的参数字符串。

–A

在跟踪输出的每一行上包含时间戳。时间戳表示一天当中的时间,并显示为包含“小时:分钟:秒.微秒”的字段。truss 命令可使用 gettimeofday()asctime() 函数来确定时间值,并以 24 小时格式输出结果。报告的时间是正在谈及的事件发生的时间。对于所有系统调用,事件是系统调用的完成,而不是系统调用的开始。有关更多信息,请参见 gettimeofday(3C)asctime(3C) 手册页。

–c

对跟踪的系统调用、故障和信号计数,而不是逐行显示跟踪。跟踪的命令终止后或 truss 被中断时,将生成汇总报告。如果还指定了 –f,则计数将包括子进程的所有受跟踪系统调用、故障和信号。

–d

在跟踪输出的每一行上包含时间戳。时间戳作为一个包含 seconds . fraction 的字段显示在行开头。这表示相对于跟踪开始的时间,以秒为单位。跟踪输出的第一行显示单个时间戳开始测量的基准时间,可以是从某个时间点以来的秒数(请参见 time(2)),也可以是日期字符串(请参见 ctime(3C)date (1))。报告的时间是正在谈及的事件发生的时间。对于所有系统共调用,事件是系统调用的完成,而不是系统调用的开始。

–D

在跟踪输出的每一行上包含时间增量。该值显示为一个包含 seconds . fraction 的字段,表示自上次报告的由 LWP 引发的事件以来,引发该事件的 LWP 所用的时间。具体来说,对于系统调用,这不属于系统调用所花费的时间。

–e

显示在各个 exec()spawn() 系统调用中传递的环境字符串。

–E

在跟踪输出的每一行上包含时间增量。The value appears as a field containing seconds.fraction and represents the difference in time elapsed between the beginning and end of a system call(wall clock time).

–D 选项相反,这是在系统调用内花费的时间量。

–G

在跟踪输出的每一行上包含时间增量。The value appears as a field containing seconds.fraction and represents the system time accumulated between the beginning and end of a system call.

–f

跟随 fork()vfork()spawn() 创建的所有子项并在跟踪输出中包含其信号、故障和系统调用。通常,仅跟踪第一级命令或进程。如果指定了 –f,进程 ID 将包含在跟踪输出的各个行中,以指示哪个进程执行了系统调用或接收了信号。

–i

不会显示可中断的休眠系统调用。某些系统调用(如终端设备或管道上的 open()read())可以无限期休眠,并可中断。truss 通常会在此类休眠系统调用保持休眠状态超过一秒时报告这些系统调用。系统调用在完成后会再次进行报告。–i 选项将使此类系统调用仅在完成时报告一次。

–I

如果可能,显示解释的系统调用。许多历史系统调用陷阱已由更通用的现代系统调用陷阱取代。例如,open() 系统调用在 libc 中作为对通用 openat() 系统调用陷阱的调用来实现。

int
open(path, oflag, mode)
{
     return (openat(AT_FDCWD, path, oflag, mode));
}

truss 命令通常报告底层 openat() 系统调用陷阱,即使应用程序的源代码调用 open() 函数。–I 选项会导致 truss 猜测应用程序实际调用了什么。所以,在此情况下,由于 openat() 函数的第一个参数为 AT_FDCWD,因此系统调用报告为 open(),即使应用程序实际调用了 openat(AT_FDCWD, ...)

–l

在跟踪输出的各个行中包含负责轻量级进程 (lightweight process, LWP) 的 ID。如果还指定了 –f,进程 ID 和 LWP ID 均会包含在内。

–m [!]fault,...

要跟踪或排除的计算机故障。将跟踪在以逗号分隔的列表中指定的那些故障跟踪。故障可以按名称或编号进行指定(请参见 <sys/fault.h>)。 如果列表以 ! 开头,将从跟踪输出中排除指定的故障。缺省值为 –mall –m !fltpage

–M [!]fault,...

停止进程的计算机故障。将指定的故障添加至 –m 指定的集合中。 如果引发指定的故障之一,则 truss 将保留该进程处于停止和弃用状态(请参见 –T 选项)。缺省值是 –M!all

–o  outfile

要用于跟踪输出的文件。缺省情况下,输出的是标准错误。

–p

trusscommand 参数解释为现有进程的进程 ID 列表(请参见 ps (1)),而不是要执行的命令。truss 控制各个进程,并在进程的用户 ID 和组 ID 与该用户的用户 ID 和组 ID 匹配或该用户是特权用户时,开始对该进程进行跟踪。用户可以通过将 /thread-id 附加到进程 ID 来仅跟踪选定的线程。可使用 -, 分隔符选择多个线程。例如,/1,2,7-9 将跟踪线程 1278 以及 9。 也可在目录 /proc 中使用进程名指定进程,例如 /proc/12345

–r [!]fd,...

显示任一指定文件描述符上每个 read() 的 I/O 缓冲区的完整内容。输出格式化为每行 32 字节,其中各个字节显示为 ASCII 字符(前面留有一个空白)或双字符 C 语言转义序列,以便控制诸如水平制表符 ( \ t) 和换行符 ( \ n) 等的字符。 如果不能进行 ASCII 解释,则字节将采用双字符十六进制表示。(每个受跟踪 print >read() 的 I/O 缓冲区的前 12 个字节即使在没有 –r 的情况下也会显示。)缺省值是 –r!all

–s [!]signal,...

要跟踪或排除的信号。将跟踪在逗号分隔的列表中指定的那些信号。跟踪输出将报告各个指定信号的接收情况,即使该信号受到忽略(未阻塞)。(不会收到阻塞的信号,直至将其解除阻塞。)信号可以按名称或编号进行指定(请参见 <sys/signal.h>)。 如果列表以 ! 开头,将从跟踪输出中排除指定的信号。Default is –sall.

–N

Report only system calls which have returned an error.

–S [!]signal,...

停止进程的信号。将指定的信号添加至 –s 指定的集合中。 如果收到一个指定信号,则 truss 将保留该进程处于停止和弃用状态(请参见 –T 选项)。缺省值是 –S!all

–t [!]syscall ,...

要跟踪或排除的系统调用。将跟踪在逗号分隔的列表中指定的这些系统调用。如果列表以 ! 开头,则指定的系统调用将从跟踪输出中排除。缺省值是 –tall

–T [!]syscall ,...

指定停止进程的系统调用。将指定的系统调用添加至 –t 指定的集合中。 如果遇到指定的系统调用之一,truss 将保留该进程处于停止和弃用状态。即,truss 将释放该进程并退出,但在涉及的系统调用完成时保留该进程处于停止状态。然后,可以向该停止的进程应用调试程序或其他进程检查工具(请参见 proc (1))。可将具有相同或不同选项的 truss 重新应用于该停止的进程以继续跟踪。缺省值是 –T!all

以此种方式保持停止状态的进程无法通过应用 kill –CONT 重新启动,因为它是通过 /proc 基于特定事件停止的,而不是由停止信号的缺省操作停止的(请参见 signal.h(3HEAD) )。 prun(1) 命令(proc(1) 中有述)可用于将已停止进程设置为再次运行。

–u [!]lib,... :[:][!]func, . . .

用户级函数调用跟踪。lib, . . .是动态库名的逗号分隔列表,不包括 ".so.n" 前缀。func, . . .是函数名的逗号分隔列表。在两种情况下,名称都可以包括名称匹配元字符 *,?,[],它们与 sh(1) 的那些元字符具有相同意义,但是它们应用于库/函数名称空间,而不是文件。空库或函数列表的缺省设置是 *,跟踪库中所有库或函数。两个列表中任一个上出现前导 ! 将指定不受跟踪的排除列表、库或函数的名称。排除一个库将排除该库中的所有函数;库排除列表后的任何函数列表都将被忽略。

: 可以分离库列表与函数列表,意味着跟踪从库外到库内的调用,但忽略库中其他函数对同一库中函数的调用。双 : : 意味着跟踪所有调用,而不管来源。

库模式与可执行文件或动态链接程序均不匹配,除非存在确切匹配(l*ld.so.1 不匹配)。 要跟踪这些目标文件中的函数,必须准确指定名称,如:

truss -u a.out -u ld ...

a.out 是用于实现此目的的文字名称;其不代表可执行文件的名称。跟踪 a.out 函数调用意指所有调用(缺省值是 ::)。

可以指定多个 –u 选项,其遵循自左向右的顺序。执行函数调用的轻量级进程的 ID 和线程的 ID 包括在该调用的跟踪输出中,分别以斜杠 (/) 和 at 符号 (@) 字符分隔。

–U [!]lib, . . . :[:][!]func, . . .

停止进程的用户级函数调用。将指定的函数添加至 –u 指定的集合中。 如果调用指定的函数之一,则 truss 将保留该进程处于停止和弃用状态(请参见 –T 选项)。

–v [!]syscall ,...

详细模式。显示按地址传递至指定系统调用(如果由 –t 跟踪)的任何结构的内容。 将显示输入值以及由操作系统返回的值。对于用作输入和输出的任何字段,仅显示输出值。缺省值是 –v!all

–w [!]fd,...

显示任一指定文件描述符上每个 write() 的 I/O 缓冲区的内容(请参见 –r 选项)。缺省值是 –w!all

–x [!]syscall ,...

以原始格式(通常为十六进制)而不是符号方式显示指定系统调用(如果由 –t 跟踪)的参数。 有些技术高手希望看到原始位。缺省值是 –x!all

有关 –t–T–v–x 选项接受的系统调用名称,请参见man pages section 2: System Calls。系统调用编号也会被接受。

如果使用 truss 初始化并跟踪指定的命令且使用了 –o 选项,或者如果将标准错误输出重定向至非终端文件,则 truss 在运行中将忽略挂起、中断和退出信号。这将简化对从终端捕捉中断和退出信号的交互式程序的跟踪。

如果跟踪输出保持定向至终端,或者如果现有进程受到跟踪(–p 选项),则 truss 将通过释放所有受跟踪的进程并退出来响应挂起、终端和退出信号。这使得用户能够终止过多的跟踪输出并释放之前就存在的进程。释放的进程将正常继续运行,好像从未被碰过一样。

跟踪现有进程时,truss 将在退出时释放这些进程并将其设置为运行状态。其中包括由于信号导致的退出,如 SIGINTSIGHUPSIGQUIT。这使得用户能够终止过多的跟踪输出并释放之前就存在的进程。释放的进程将正常继续运行,好像从未被碰过一样。

示例

示例 1 跟踪命令

以下示例将跟踪记录终端上的 find(1) 命令:

example$ truss find . -print >find.out
示例 2 跟踪常见系统调用

以下示例仅显示了打开、关闭、读取和写入系统调用的跟踪记录:

example$ truss -t open,close,read,write find . -print >find.out
 
示例 3 跟踪 Shell 脚本

以下示例将跟踪记录文件 truss.out 上的 spell (1) 命令:

example$ truss -f -o truss.out spell document

spell 是一个 shell 脚本,因此需要 –f 标志以跟踪 shell 以及由此 shell 创建的进程。 (该 spell 脚本将运行一个八进程的流水线。)

示例 4 缩短输出

以下示例将缩短输出:

example$ truss nroff -mm document >nroff.out
 

因为 97% 的输出报告 lseek()read ()write() 系统调用。要缩短输出:

example$ truss -t !lseek,read,write nroff -mm document
 >nroff.out 
示例 5 跟踪来自 C 库外部的库调用

以下示例将跟踪从 C 库外部对 C 库内任意函数进行的所有用户级调用:

example$ truss -u libc ...
示例 6 跟踪来自 C 库内部的库调用

以下示例包括从 C 库自身内对 C 库中函数进行的调用:

example$ truss -u libc:: ...
示例 7 跟踪非 C 库的库调用

以下示例将跟踪对除 C 库以外的任意库进行的所有用户级调用:

example$ truss -u '*' -u !libc ...
示例 8 跟踪 printfscanf 函数调用

以下示例将跟踪对 C 库内所含 printf 和 scanf 系列中的函数进行的所有用户级调用:

example$ truss -u 'libc:*printf,*scanf' ...
示例 9 跟踪每个用户级函数调用

以下示例将跟踪从任意位置到任意位置的每个用户级函数调用:

example$ truss -u a.out -u ld:: -u :: ...
示例 10 详细跟踪系统调用

以下示例将详细跟踪进程 #1 init(8) 的系统调用活动(如果您是特权用户):

example# truss -p -v all 1

中断 truss 会将 init 返回至正常运行状态。

示例 11 显示跟踪的时间

以下示例显示了每次系统调用的当前时间戳:

example$ truss -A a.out
示例 12 Displaying system time consumed during a system call

The -E example shows wall clock time accumulated by the nanosleep system call:

example$ truss -E -t nanosleep /bin/sleep 1
1.000241    nanosleep(0xFFFFFE9F63C05E00, 0xFFFFFE9F63C05DF0) = 0
	          

The -G example shows system time (time executing in kernel) accumulated by the nanosleep system call:

example$ truss -G -t nanosleep /bin/sleep 1
nanosleep(0xFFFFFED318188A60, 0xFFFFFED318188A50) (sleeping...)
0.002761    nanosleep(0xFFFFFED318188A60, 0xFFFFFED318188A50) = 0

文件

/proc/*

进程文件

属性

有关下列属性的说明,请参见 attributes(7)

属性类型
属性值
可用性
system/core-os

另请参见

date(1)find(1)proc(1)ps(1)sh(1)spell(1)exec(2)fork(2)lseek(2)open(2)read(2)spawn(2)time(2)vfork(2)write(2)ctime(3C)signal.h(3HEAD)Intro(3)proc(5)attributes(7)mwac(7)privileges(7)threads(7)tpd(7)init(8)

man pages section 2: System Calls

附注

man pages section 2: System Calls中描述的一些系统调用与实际操作系统界面不同。请勿对与该文档中描述的跟踪输出之间的微小差异表示惊讶。

每个计算机故障(缺页除外)都会向引发该故障的 LWP 发送信号。已接收信号的报告紧跟在每个计算机故障(缺页除外)报告后,除非该信号被阻塞。

操作系统将对进程跟踪强制执行某些安全限制。尤其是,如果命令的目标文件 (a.out) 不能由用户读取,则该用户无法跟踪此命令;setuid 和 setgid 命令只能由特权用户进行跟踪。除非由特权用户运行,否则 truss 将无法控制执行 set-id 或不可读目标文件的 exec() 的任何进程;此类进程将继续从 exec()spawn() 的点继续正常运行,但与 truss 无关。

为避免与其他控制进程冲突,如果通过 /proc 接口检测到某个进程正在由另一个进程控制,则 truss 不会跟踪该进程。这使得 truss 可以应用于基于 proc(5) 的调试器以及它自身的其他实例。

假设标准制表停止位置已设置的情况下(每八个位置),跟踪输出将包含制表符。

多个进程或多线程进程(包含多个 LWP 的进程)的跟踪输出不会按严格的时间顺序生成。例如,某个管道上的 read() 可能在对应的 write() 之前报告。 对于任何一个 LWP(传统进程只包含一个),输出将严格按照时间顺序生成。

跟踪多个进程时,truss 将作为每个受跟踪进程的一个控制进程运行。对于上述 spell 命令的示例,spell 自身将使用 9 个进程槽,一个用于该 shell,8 个用于包含 8 个成员的流水线,同时 truss 会添加另外 9 个进程,所以总共是 18 个。

并非所有可能系统调用中传递的所有可能结构都会显示在 –v 选项之下。

Multiple -d, -D, -E and -G options are printed in the order -d, -D, -E, -G irrespective of the order that they are entered on the command line.

truss 报告由于缺少特权导致系统调用返回错误时,truss 在错误代码后显示简单的特权名称,或复杂的特权描述。有关更多信息,请参见 privileges(7) 手册页。该复杂的描述可以由以下内容组成:

[ALL]

对于请求的操作,此进程需要所有特权。

[MULTIPLE]

此进程缺少多个特权。

[ZONE]

此进程缺少区域中的可用特权之一(ALL 的区域本地变体)

[GLOBAL]

请求的操作要求进程在全局区域中运行。

[MWAC]

请求的操作违反适用于进程的 mwac(7) 策略。

[TPD]

请求的操作违反了 tpd(7) 策略。

[CLEARANCE]

进程安全许可不足以执行请求的操作。