Yuk*_*awa 4 linux shell aix signals sed
我想捕获 signal SIGTSTP,就像这样简单:
trap "" SIGTSTP
Run Code Online (Sandbox Code Playgroud)
然而,纯 shell ( sh) 不支持信号名称,因此陷阱必须使用信号编号来代替,如下所示:
trap "" 20
Run Code Online (Sandbox Code Playgroud)
问题:信号编号取决于操作系统,因此 Linux 中的 SIGTSTP 为 20,但在 AIX 中为 18。
因此,为了使其通用,我决定从 的结果中提取信号编号trap -l。原始输入是:
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGEMT 8) SIGFPE
9) SIGKILL 10) SIGBUS 11) SIGSEGV 12) SIGSYS
13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGURG
17) SIGSTOP 18) SIGTSTP 19) SIGCONT 20) SIGCHLD
21) SIGTTIN 22) SIGTTOU 23) SIGIO 24) SIGXCPU
25) SIGXFSZ 27) SIGMSG 28) SIGWINCH 29) SIGPWR
30) SIGUSR1 31) SIGUSR2 32) SIGPROF 33) SIGDANGER
34) SIGVTALRM 35) SIGMIGRATE 36) SIGPRE 37) SIGVIRT
38) SIGALRM1 39) SIGWAITING 50) SIGRTMIN 51) SIGRTMIN+1
52) SIGRTMIN+2 53) SIGRTMIN+3 54) SIGRTMAX-3 55) SIGRTMAX-2
56) SIGRTMAX-1 57) SIGRTMAX 60) SIGKAP 61) SIGRETRACT
62) SIGSOUND 63) SIGSAK
Run Code Online (Sandbox Code Playgroud)
我无法使用grep,因为我需要的功能 ,--only-matching并不总是受支持。trap -l | grep -oE "[0-9]+\) SIGTSTP" | cut -d')' -f1运行良好,但仅限于 Linux。
sed由于这里描述的贪婪问题,我也未能使用
所以trap -l | sed -nr 's/.*([0-9]+)\) SIGTSTP.*/\1/p'只返回8,不返回18
我想让提取尽可能通用,所以我不会假设SIGTSTP它是两位数代码,即使实际上它是。
有什么建议吗?
要通过、或中的名称获取信号编号,您可以简单地使用:bashkshzsh
kill -l TSTP # -> e.g., 18 - case doesn't matter, but do not use the "SIG" prefix
Run Code Online (Sandbox Code Playgroud)
由于它使用kill 内置的(而不是外部实用程序版本/bin/kill),因此它应该适用于支持这些 shell 的任何平台。
这是一个符合 POSIX 标准的解决方案,不依赖于特定的 shell:
/bin/kill -l | tr -s '[:blank:]' '\n' |
awk -v name='TSTP' 'toupper($0) == toupper(name) {print NR}' # don't use "SIG" prefix
Run Code Online (Sandbox Code Playgroud)
kill实用程序及其/bin/kill选项用于-l列出信号。虽然POSIX 规范kill规定了输出格式,但它并不强制要求按特定顺序列出信号。然而,有意义的顺序是按它们的数值排列的,在实践中似乎就是这种情况,并且这种方法依赖于它。/bin/kill,与 bash、ksh、zsh 和 dash 中的内置函数不同,它不会在 Linux上kill报告信号。SIGRTMINSIGRTMAX至于逆运算 -通过信号编号获取信号名称- 使用kill -l <number>,例如:
kill -l 18 # -> e.g., 'TSTP'
Run Code Online (Sandbox Code Playgroud)
、、和kill中的内置函数都支持这一点。bashkshzshdash
外部/bin/kill实现因上述语法而异:
macOS、GNU kill:以上形式有效。
procps-ng ,如 Ubuntu 18.04 或更低kill版本中所示,例如:仅接受(或);也就是说,选项参数必须直接附加到选项上,这是符合 POSIX 的语法,假设信号号是可选的选项参数(其本身列出了所有信号名称);请参阅POSIX 实用程序参数语法。
kill -l18kill --list=18-l-l
不幸的是,上面列出的其他实现仅支持(可能不明确的)-l 18形式。
Ubuntu 19.10附带的 procps-ng 版本(procps-ng 3.3.15)支持这两种形式(也支持--list 18)。向亚诺的帮助致敬。