如何检查进程正在侦听哪些信号?

Jan*_*der 87 process signals

如何验证正在运行的进程是否会捕获信号、忽略它或阻止它?理想情况下,我希望查看信号列表,或者至少不必实际发送信号进行检查。

Jan*_*der 119

在 Linux 下,你可以找到你的进程的 PID,然后查看/proc/$PID/status. 它包含描述哪些信号被阻塞 (SigBlk)、忽略 (SigIgn) 或捕获 (SigCgt) 的行。

# cat /proc/1/status
...
SigBlk: 0000000000000000
SigIgn: fffffffe57f0d8fc
SigCgt: 00000000280b2603
...
Run Code Online (Sandbox Code Playgroud)

右边的数字是位掩码。如果将其从十六进制转换为二进制,则每个 1 位代表一个捕获的信号,从右到左从 1 开始计数。因此,通过解释 SigCgt 行,我们可以看到我的init进程正在捕获以下信号:

00000000280b2603 ==> 101000000010110010011000000011
                     | |       | ||  |  ||       |`->  1 = SIGHUP
                     | |       | ||  |  ||       `-->  2 = SIGINT
                     | |       | ||  |  |`----------> 10 = SIGUSR1
                     | |       | ||  |  `-----------> 11 = SIGSEGV
                     | |       | ||  `--------------> 14 = SIGALRM
                     | |       | |`-----------------> 17 = SIGCHLD
                     | |       | `------------------> 18 = SIGCONT
                     | |       `--------------------> 20 = SIGTSTP
                     | `----------------------------> 28 = SIGWINCH
                     `------------------------------> 30 = SIGPWR
Run Code Online (Sandbox Code Playgroud)

(我通过kill -l从 bash运行找到了数字到名称的映射。)

编辑:根据大众需求,POSIX sh 中的脚本。

sigparse () {
    i=0
    # bits="$(printf "16i 2o %X p" "0x$1" | dc)" # variant for busybox
    bits="$(printf "ibase=16; obase=2; %X\n" "0x$1" | bc)"
    while [ -n "$bits" ] ; do
        i="$(expr "$i" + 1)"
        case "$bits" in
            *1) printf " %s(%s)" "$(kill -l "$i")" "$i" ;;
        esac
        bits="${bits%?}"
    done
}

grep "^Sig...:" "/proc/$1/status" | while read a b ; do
        printf "%s%s\n" "$a" "$(sigparse "$b")"
    done # | fmt -t  # uncomment for pretty-printing
Run Code Online (Sandbox Code Playgroud)

  • 如果信号列在“SigBlk”下,它是否也出现在“SigCgt”中?因为通过阻止它,它只是意味着稍后会重新发送信号,对吗?需要捕获吗? (2认同)
  • @Kusalananda:Linux 并不意味着 Bash——例如,小型嵌入式平台经常使用 Busybox——但 POSIX 合规性几乎可以保证任何现代 `/bin/sh`。你是对的“本地”;我会清理它。 (2认同)

ala*_*anc 23

在 Solaris 上,运行psig进程 id 以获取信号列表以及它们将如何处理。

例如:

bash-4.2$ psig $$
11088:  bash
HUP     caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
INT     caught  sigint_sighandler   0
QUIT    ignored
ILL     caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
TRAP    caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
ABRT    caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
EMT     caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
FPE     caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
KILL    default
BUS     caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
SEGV    caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
SYS     caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
PIPE    caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
ALRM    caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
TERM    ignored
USR1    caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
USR2    caught  termsig_sighandler  0   HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
CLD     blocked,caught  0x4898e8    RESTART
PWR     default
WINCH   caught  sigwinch_sighandler 0
[...]
Run Code Online (Sandbox Code Playgroud)

这表明 SIGHUP、SIGILL 等都将被同一个信号处理函数捕获,该函数termsig_sighandler将在不使用任何可以通过 设置的标志的情况下运行sigaction,并且在信号处理程序处于正在运行(在这种情况下,所有信号处理程序都使用相同的信号处理程序,因此在已经运行时不会重新输入)。还可以看到 SIGQUIT & SIGTERM 会被忽略,SIGKILL & SIGPWR 使用系统默认的信号动作,而 SIGCLD 指定了 RESTART 标志,所以如果它的信号处理程序中断了系统调用,系统调用会重新启动。


eri*_*ers 5

(这个答案类似于@user18096 的答案,因为它围绕@Jander 的答案创建了一个脚本。)

我已经编写了psig script一个 PID(或所有 PID)并从/proc/<PID>/status.

示例输出:

% ./psig -a
[     1] Signals Queued: 8/773737
[     1] Signals Pending:
[     1] Signals Pending (Shared):
[     1] Signals Blocked:
[     1] Signals Ignored: SIGPIPE
[     1] Signals Caught: SIGHUP,SIGINT,SIGABRT,SIGUSR1,SIGSEGV,SIGALRM,SIGTERM,SIGCHLD,SIGPWR
...
[ 31001] Signals Queued: 0/773737
[ 31001] Signals Pending:
[ 31001] Signals Pending (Shared):
[ 31001] Signals Blocked: SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGTRAP,SIGABRT,SIGBUS,SIGFPE,SIGUSR1,SIGUSR2,SIGPIPE,SIGALRM,SIGTERM,SIGSTKFLT,SIGCHLD,SIGCONT,SIGTSTP,SIGTTIN,SIGTTOU,SIGURG,SIGXCPU,SIGXFSZ,SIGPROF,SIGWINCH,SIGIO,SIGPWR,SIGSYS,SIGRTMIN,SIGRTMIN+1,SIGRTMIN+2,SIGRTMIN+3,SIGRTMIN+4,SIGRTMIN+5,SIGRTMIN+6,SIGRTMIN+7,SIGRTMIN+8,SIGRTMIN+9,SIGRTMIN+10,SIGRTMIN+11,SIGRTMIN+12,SIGRTMIN+13,SIGRTMIN+14,SIGRTMIN+15,SIGRTMAX-14,SIGRTMAX-13,SIGRTMAX-12,SIGRTMAX-11,SIGRTMAX-10,SIGRTMAX-9,SIGRTMAX-8,SIGRTMAX-7,SIGRTMAX-6,SIGRTMAX-5,SIGRTMAX-4,SIGRTMAX-3,SIGRTMAX-2,SIGRTMAX-1,SIGRTMAX
[ 31001] Signals Ignored: SIGHUP,SIGINT,SIGQUIT,SIGPIPE,SIGXFSZ
[ 31001] Signals Caught: SIGBUS,SIGUSR1,SIGSEGV,SIGUSR2,SIGALRM,SIGTERM,SIGVTALRM
Run Code Online (Sandbox Code Playgroud)

注意事项:

  • Linux 特定的答案。
  • 可能需要一个相对较新的 Python 版本来运行脚本,它使用withOrderedDict.