利用truss在Solaris下定位问题

在Solaris下面,如果需要跟踪系统的调用,以便查找和定位问题,truss是一个非常有用的命令,下面就对这个命令做详细介绍。

truss 命令
用途

跟踪进程的系统调用、动态装入的用户级函数调用、接收的信号和造成的机器故障。

语法

truss [ -f] [ -c] [ -a] [ -l ] [ -d ] [ -D ] [ -e] [ -i] [ { -t | -x} [!] Syscall […] ] [ -s [!] Signal […] ] [ { -m }[!] Fault […]] [ { -r | -w} [!] FileDescriptor […] ] [ { -u } [!]LibraryName […]:: [!]FunctionName [ … ] ] [ -o Outfile] {Command| -p pid [. . . .]}

描述
truss 命令执行指定命令或附加在列出进程标识上,并产生对系统调用、接收的信号和进程造成的机器故障的跟踪。每行跟踪输出报告 Fault 或 Signal 名称或 Syscall 名称和参数及返回值。系统库定义的子例程对于内核的严格系统调用并不是必要的。truss 命令不报告这些子例程,而是报告子例程的基本系统调用。 可能的话,系统调用参数使用有关系统头文件定义符号显示。对于路径名指针参数,truss 显示指向的字符串。未定义的系统调用缺省显示系统名称、所有八个可能的变量及十六进制格式的返回值。

  当 -o 标志与 truss 一起使用,或标准错误改指向非终端文件时,truss 忽略挂断、中断和信号进程。它促进跟踪交互式程序从终端获得 interrupt 和 quit 信号。

  若跟踪输出保持指向终端或跟踪现存过程(使用 -p 标志),truss 对 hangup、interrupt 和 quit 信号做出反应,释放所有跟踪进程并退出。它使用户可终止过多的跟踪输出并释放前现存进程。释放进程继续到功能恢复正常。

  对与含有一列变量的选项,名称 all 可用作指定列表中所有可能成员的简写。以 ! 开头的列表,选项含义是相反的(示例:排除而非跟踪)。同一选项可能指定为多种表现形式。同一列表的相同名称,后面的选项(右边选项)覆盖前面的选项(左边选项)。

  除了页面故障以外的所有机器故障均导致公布信号到发生故障进程。除了进程阻塞信号,每一机器故障报告后立即给出接收的信号报告。

  为避免与其它控制进程冲突,truss 不跟踪由其检测到并由带有 /proc 接口的另一进程控制的进程。

  多进程跟踪输出不是按严格的时间顺序产生。示例:管道读取可以在相应的写之前报告。然而每一进程输出是严格按时间排序。跟踪输出含有制表符,且每八个位置设置标准制表符停止位。

  系统跟踪子进程时可运行于每个用户进程槽之外。这是因为跟踪多个进程时,truss 作为所跟踪进程的控制进程运行,将用于所给进程的进程槽数目加倍。运行多进程跟踪之前应考虑通常系统强制的每个用户 25 进程的限制。

  处理多个进程时,truss 使用共享内存和信号。例如:在多进程标识下使用 -f 标志和 -p 标志。需要的话,跟踪可运行于非配置系统中。这些情况下,truss 生成警告消息并继续跟踪。然而跟踪输出可能断章取义,-c 标志输出仅报告顶级命令或第一个进程标识,不计数子进程。

  操作系统为进程跟踪强加某种安全性限制。必须有跟踪命令的存取特权。 set-uid 和 set-gid 进程仅可由特权用户跟踪。除由特权用户运行外,truss 命令无法控制执行 set-id 或不可读对象代码的进程。这些未跟踪的进程从执行点保持正常并与 truss 无关。

  truss 输出提到的轻量级进程(LWP)是真正的内核线程。选项 -l 在每行跟踪输出显示 LWP 标识(即线程标识)。

  AIX 库的用户库函数有静态和动态两种装入函数调用。选项 -u 跟踪仅用于动态装入函数调用。

  -u 选项提供动态装入函数调用的用户级函数调用跟踪。此选项产生函数调用的进入/退出跟踪。

  标志

  -a 显示在每一执行系统调用中传递的参数字符串。

  -c 计数跟踪系统调用、故障和信号而不是逐行显示跟踪结果。跟踪命令终止或 truss 中断时生成摘要报告。若还使用 -f 标志,计数包含所有跟踪的系统调用、故障和子进程信号。

  -d 每行输出包含时间戳记。时间从跟踪开始以每秒显示。跟踪输出的第一行显示测量单个时间戳记的基本时间。缺省不显示时间戳记。

  -D 每行输出显示增量时间。增量时间表示从由该线程引起的最后报告事件起计时引起事件的 LWP 的逝去时间。缺省不显示增量时间。

  -e 显示在每一执行系统调用中传递的环境字符串。

  -f 跟在 fork 系统调用产生的所有子进程之后,并包含跟踪输出中的信号、故障和系统调用。 通常,仅跟踪第一级命令和进程。如果指定 -f 标志,进程标识与每行跟踪输出一起显示哪个进程执行系统调用或接收信号。

  -i 阻止显示可中断的休眠系统调用。某些终端设备或管道的系统调用,如 open 和 kread,可无限期休眠且是可中断的。通常,如果这种休眠系统调用保持超过一秒休眠,truss 将报告。系统调用完成后一秒内报告系统调用。-i 标志使这种系统调用完成后仅报告一次。

  -l 显示有关 LWP 进程的标识(线程标识)及 truss 输出。输出中缺省不显示 LWP 标识。

  -m [!]Fault 跟踪进程中的机器故障。必须用逗号分隔要跟踪的机器故障。可按名称或代码指定故障(参见 sys/procfs.h 头文件)。如果列表以符号“!”开始,指定的故障不再被跟踪且不显示跟踪输出。缺省值是 -mall -m!fltpage。

  -o Outfile 指定用于跟踪输出的文件。缺省时输出指向标准错误。

  -p 将参数作为一列现存进程的进程标识而不是要执行的命令解释到 truss。 倘若进程用户标识或组标识与用户的用户标识或组标识匹配或者用户是特权用户,truss 控制并开始跟踪每个进程。

  -r [!] FileDescriptor 显示每一个读取指定文件描述符的 I/O 缓冲区全内容。输出采用每行 32 字节的格式并以 ASCII 字符(跟在空格后)形式显示字节,或以控制字符的双字符 C 语言转义序列形式显示字节,如水平制表符 (\t) 或换行符 (\n)。如果不能解释成 ASCII 格式,字节以双字符十六进制形式显示。即使没有 -r 标志,仍显示跟踪读取 I/O 缓冲区的前 16 位字节。缺省值是 -r!all。

  -s [!] Signal 允许列出要跟踪或除去的 Signals。跟踪列表中指定的信号(由逗号分隔)。信号被忽略但不是被进程阻塞时,跟踪输出仍报告每个指定信号的接收。直到进程释放时才可接收阻塞信号。可按名称或代码指定信号(参见 sys/signal.h)。如果该列表以“!”符号开头,则列出的信号将从显示跟踪输出中排除。缺省值是 -s all。

  -t [!] Syscall 包含或排除来自跟踪进程的系统调用。要跟踪的系统调用必须在列表中指定并以逗号分隔。如果列表以符号“!”开始,指定的系统调用将被从跟踪输出中排除。缺省值是 -tall。

  -u [!] [LibraryName […]::[!]FunctionName […] ]

  跟踪来自用户库动态装入的用户级函数调用。 LibraryName 是逗号分隔的库名列表。FunctionName 是逗号分隔的函数名列表。两种情况下的名称都包含名称匹配元字符 *、? 和 [],这些字符与由 shell 解释的意义相同,但适用于库/函数名称空间而非文件。

  任一列表中以 ! 开头的列指定不跟踪库或函数的排除名称列表。除去库将除去该库中所用函数。忽略库除去列表后的任何函数列表。可指定多个 -u 选项并将它们从左到右排列。缺省不跟踪库/函数调用。

  -w [!] FileDescriptor 显示列出文件描述符每个写过程的 I/O 缓冲区内容(参见 -r)。缺省值是 -w!all。

  -x [!] Syscall 以原始格式显示跟踪系统调用指定参数的数据,通常按十六进制而不是符号化方式。缺省值是 -x!all.

  示例

  1. 在终端上跟踪 find 命令,输入:

  truss find . -print >find.out

  2. 跟踪 lseek、close、statx 和开放系统调用,输入:

  truss -t lseek,close,statx,open find . -print > find.out

  3. 显示 find 命令的线程标识和常规输出,输入:

  truss -l find . -print >find.out

  4. 显示 find 命令的时间戳记和常规输出,输入:

  truss -d find . -print >find.out

  5. 显示 find 命令的增量时间和常规输出,输入:

  truss -D find . -print >find.out

  6. 运行 ls 命令时,在 libc.a 库中跟踪 malloc() 函数调用及除去 strlen() 函数调用,输入:

  truss -u libc.a::malloc,!strlen ls

  7. 运行 ls 命令时,跟踪 libc.a 库中名称以“m”开头的所有函数调用,输入:

  truss -u libc.a::m*,!strlen ls

  8. 运行可执行 foo 时,跟踪来自 libcurses.a 库的所有函数调用及除去来自 libc.a 的调用,输入:

  truss -u libcurses.a,!libc.a::* foo

  9. 运行可执行 foo 时,跟踪来自 libcurses.a 的 refresh() 函数调用和来自 libc.a 的 malloc() 函数调用,输入:

  truss -u libc.a::malloc -u libcurses.a::refresh foo

下面是一个英文版本的介绍和范例。

Truss is used to trace the system/library calls (not user calls) and signals made/received by a new or existing process. It sends the output to stderr.

NOTE: Trussing a process throttles that process to your display speed. Use -wall and -rall sparingly.

Truss usage

truss -a -e -f -rall -wall -p
truss -a -e -f -rall -wall

-a Show arguments passed to the exec system calls
-e Show environment variables passed to the exec system calls
-f Show forked processes
(they will have a different pid: in column 1)
-rall Show all read data (default is 32 bytes)
-wall Show all written data (default is 32 bytes)
-p Hook to an existing process (must be owner or root) Specify a program to run

Truss examples

# truss -rall -wall -f -p # truss -rall -wall lsnrctl start
# truss -aef lsnrctl dbsnmp_start

A Running Example (using the date command)

# truss -d date

Base time stamp: 1066157908.5731 [ Tue Oct 14 14:58:28 EDT 2003 ]
0.0000 execve(“/usr/bin/date”, 0xFFBEF29C, 0xFFBEF2A4) argc = 1
0.0449 mmap(0x00000000, 8192, PROT_READ|PROT_WRITE|PROT_EXEC,MAP_PRIVATE|MAP_ANON, -1, 0) = 0xFF3A0000
0.0453 resolvepath(“/usr/lib/ld.so.1”, “/usr/lib/ld.so.1”, 1023) = 16
0.0457 open(“/var/ld/ld.config”, O_RDONLY) Err#2 ENOENT
0.0460 open(“/usr/lib/libc.so.1”, O_RDONLY) = 3
0.0463 fstat(3, 0xFFBEE9C4) = 0
0.0464 mmap(0x00000000, 8192, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0xFF390000
0.0466 mmap(0x00000000, 794624, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0xFF280000
0.0470 mmap(0xFF33A000, 24652, PROT_READ|PROT_WRITE|PROT_EXEC,MAP_PRIVATE|MAP_FIXED, 3, 696320) = 0xFF33A000
0.0474 munmap(0xFF32A000, 65536) = 0
0.0479 memcntl(0xFF280000, 113332, MC_ADVISE, MADV_WILLNEED, 0, 0) = 0
0.0481 close(3) = 0
0.0483 open(“/usr/lib/libdl.so.1”, O_RDONLY) = 3
0.0485 fstat(3, 0xFFBEE9C4) = 0
0.0487 mmap(0xFF390000, 8192, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED,3, 0) = 0xFF390000
0.0490 close(3) = 0
0.0493 open(“/usr/platform/SUNW,Ultra-5_10/lib/libc_psr.so.1”, O_RDONLY) = 3
0.0496 fstat(3, 0xFFBEE854) = 0
0.0497 mmap(0x00000000, 8192, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0xFF380000
0.0500 mmap(0x00000000, 16384, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0xFF370000
0.0502 close(3) = 0
0.0514 munmap(0xFF380000, 8192) = 0
0.0521 brk(0x00022420) = 0
0.0523 brk(0x00024420) = 0
0.0526 time() = 1066157908
0.0531 open(“/usr/share/lib/zoneinfo/US/Eastern”, O_RDONLY) = 3
0.0533 read(3, ” T Z i f\0\0\0\0\0\0\0\0″.., 8192) = 1250
0.0536 close(3) = 0
0.0542 ioctl(1, TCGETA, 0xFFBEEFDC) = 0
Tue Oct 14 14:58:28 EDT 2003
0.0545 write(1, ” T u e O c t 1 4 1″.., 29) = 29
0.0547 llseek(0, 0, SEEK_CUR) = 1829
0.0549 _exit(0)

NOTE: The “truss” command works on SUN and Sequent. Use “strace” on Linux. If your operating system doesn’t support the truss and strace commands, call your system administrator to find the equivalent command on your system.

Monitor your Unix system:

Unix message files record all system problems like disk errors, swap errors, NFS problems, etc. Monitor the following files on your system to detect system problems:

# tail -f /var/adm/SYSLOG
# tail -f /var/adm/messages
# tail -f /var/log/syslog

This entry was posted in 脚本语言 and tagged . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *