查找特定系统调用 returns 特定错误的进程

Find process where a particular system call returns a particular error

在 OS X El Capitan 上,我的日志文件 system.log 有时感觉有数百行以下内容

03/07/2016 11:52:17.000 kernel[0]: hfs_clonefile: cluster_read failed - 34

但没有迹象表明发生这种情况的过程。除此之外,磁盘工具找不到文件系统的任何故障。但我仍然想知道发生了什么,在我看来 dtrace 应该非常适合找出那个错误的过程,但我被卡住了。我知道函数 return probe 但它似乎需要 PID,例如

dtrace -n 'pidXXXX::hfs_clonefile:return { printf("ret: %d", arg1); }'

有没有办法告诉 dtrace 探测所有进程?然后我将如何打印进程名称?

您可以使用 syscall 提供程序而不是 pid 提供程序来执行此类操作。类似于:

sudo dtrace -n 'syscall::hfs_clonefile*:return /errno != 0/ { printf("ret: %d\n", errno); }'

上述命令是内置的基于 DTrace 的 errinfo 实用程序中使用的命令的一个小变体。您可以在任何编辑器中查看 /usr/bin/errinfo 以了解其工作原理。

但是,至少就 DTrace 而言,在我的 El Capitan (10.11.5) 系统上没有 hfs_clonefile 系统调用:

$ sudo dtrace -l -n 'syscall::hfs*:'

   ID   PROVIDER            MODULE                          FUNCTION NAME
dtrace: failed to match syscall::hfs*:: No probe matches description

此外,不幸的是,syscall 提供程序被 El Capitan (macOS 10.11) 引入的系统完整性保护功能阻止跟踪系统进程。因此,您将不得不禁用 SIP,这会降低您系统的安全性。

你可以尝试这样的事情(我没有访问 OS X 机器来测试它)

#!/usr/sbin/dtrace -s
# pragma D option quiet

fbt::hfs_clonefile:return
/ args[ 1 ] != 0 /
{
    printf( "\n========\nprocess: %s, pid: %d, ret value: %d\n", execname, pid, args[ 1 ] );
    /* get kernel and user-space stacks */
    stack( 20 );
    ustack( 20 );
}

对于 fbt 探测器,args[ 1 ] 是由函数编辑的值 return。

只要 return 值不为零,dTrace 脚本就会从 hfs_clonefile() 中打印出进程名称、pid 和 return 值。它还添加了内核和用户 space 堆栈跟踪。这应该足以让您找到错误的来源。

无论如何,假设它在 OS X 上有效。