Linux 按信号名称查找信号号
我想捕获信号Linux 按信号名称查找信号号,linux,shell,sed,signals,aix,Linux,Shell,Sed,Signals,Aix,我想捕获信号SIGTSTP,简单如下: trap "" SIGTSTP 但是,纯shell(sh)不支持信号名,因此陷阱必须使用信号号,如下所示: trap "" 20 问题:信号号取决于操作系统,所以Linux中的SIGTSTP是20,而AIX中是18 因此,为了使其通用,我决定从trap-l的结果中提取信号号。原始输入为: 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGA
SIGTSTP
,简单如下:
trap "" SIGTSTP
但是,纯shell(sh
)不支持信号名,因此陷阱必须使用信号号,如下所示:
trap "" 20
问题:信号号取决于操作系统,所以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
我不能使用grep
,因为我需要的功能,——仅匹配,并不总是受支持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
是两位数代码,即使实际上是这样
有什么建议吗?试试这个:
trap -l | sed -nr 's/^([^0-9]*|.*[ \t])([0-9]+)\) SIGURG.*$/\2/p'
现在所有操作都正常运行
gaetano更新:我发现了一个。对于sed
版本和编写便携式sed
命令之间的差异,一些人可能仍然对这个答案感兴趣
在以下情况下,系统运行良好:
- 可以使用支持
-r
以支持扩展正则表达式的sed
实现
bash
用于执行命令,因为sed
命令需要bash
trap
内置的-l
选项产生的输出格式
- 平台的正则表达式库支持单词边界断言的
\b
这适用于OP,但并非所有平台都满足这些要求,尤其是类似BSD的平台,包括OSX
警告:
- 只有当您指定(a)完整的信号名称(例如,
SIGUSR1
vs.justSIGUSR
)即(b)不是另一个信号名称的子字符串(例如,SIGRTMAX
vs.SIGRTMAX-1
)时,可接受的解决方案才能明确工作
考虑到扩展正则表达式的功能,在支持\b
的sed-r
平台上解决这一缺点并不难(这是(非便携)公认解决方案的修订版):
请注意结尾处的交替(…|…
),它规定信号名称后面必须跟空格或行尾。
(请注意,也使用\b
一般不会起作用,因为它将在-
之前匹配,这是某些信号名称的有效部分)
以下是针对BSD类平台(包括OSX)的修改后的accept答案的(也是非便携的)等价物:
trap -l | sed -nr 's/.*\b([0-9]+)\) SIGTSTP(\s.*|$)/\1/p'
trap -l | sed -nE 's/.*[[:<:]]([0-9]+)\) SIGTSTP([[:blank:]].*|$)/\1/p'
s/^/;s/$//
只需在每行前面加上一个空格字符,这样每个信号号和信号名都保证用空格分隔,从而简化了匹配
- 注意,由于必须使用基本正则表达式,所以需要使用特殊字符。例如
(
和{
需要转义
- POSIX char.class(如
[[:blank:]]
必须用来代替快捷方式(如\s
)
- 复制符号
+
必须使用\{1,\}
进行模拟
但是,请注意,解决方案本身并不符合POSIX:
trap
是bash
中的一个内置组件,因此它的trap-l
输出格式在bash
运行的所有平台上都是相同的-但是请注意,bash
本身虽然与POSIX兼容,但它不是POSIX本身强制要求的,并且实现了POSIX标准的许多扩展-trap-l
是其中之一它们。
上述命令依赖于bash
的trap-l
输出格式,如问题所示
POSIX兼容性说明:
- 不支持
-l
,而支持,但它规定了不同的格式:
“当指定-l
选项时,每个信号的符号名称应采用以下格式书写:%s%c“,
,其中
为大写,不带SIG
前缀,
应为
或
。对于最后写入的信号,
应为
-;
e、 g.:HUP INT QUIT ILL…
规范没有规定信号的排列顺序,但在实践中,实现似乎是按数值的升序排列的
- 但是,
bash
也有一个kill
内置函数,它的-l
选项产生与trap-l
相同的输出。内置函数优先于实用程序,因此bash
kill
内置函数会对外部kill
实用程序产生阴影。因此,kill-l
bash
中的(和trap-l
)与POSIX强制格式不同,如下所示:
- 信号名称的前缀为编号,格式为
)
,后跟空格
- 信号名称具有
SIG
名称前缀
因此,bash
的kill-l
输出是主动非POSIX兼容的,除非您在POSIX模式下运行bash
(例如,通过运行shopt-so POSIX
)相比之下,ksh
、zsh
和dash
中的kill
内置项默认情况下符合POSIX强制输出格式
尝试使用单词边界约束匹配:
trap-l | sed-nr's/*\b([0-9]+)\)SIGTSTP./\1/p'
这对我来说是正确的焦油测试
trap -l |
sed -n 's/^/ /; s/$/ /; s/.*[[:blank:]]\([0-9]\{1,\}\)) SIGTSTP[[:blank:]].*/\1/p'
kill -l TSTP # -> e.g., 18 - case doesn't matter, but do not use the "SIG" prefix
/bin/kill -l | tr -s '[:blank:]' '\n' |
awk -v name='TSTP' 'toupper($0) == toupper(name) {print NR}' # don't use "SIG" prefix
kill -l 18 # -> e.g., 'TSTP'