按信号名称查找信号编号
Find signal number by signal name
我要陷阱信号SIGTSTP
,就这么简单:
trap "" SIGTSTP
然而,纯shell(sh
)不支持信号名称,因此陷阱必须使用信号编号代替,如下所示:
trap "" 20
问题:信号编号是 OS 相关的,所以 SIGTSTP 在 Linux 中是 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
,因为我需要的功能 --only-matching
并不总是受支持。 trap -l | grep -oE "[0-9]+\) SIGTSTP" | cut -d')' -f1
效果很好,但只适用于 Linux.
我也因为here
描述的贪心问题而使用sed
失败
所以trap -l | sed -nr 's/.*([0-9]+)\) SIGTSTP.*//p'
只有returns8
,没有18
我想让提取尽可能通用,所以我不会假设 SIGTSTP
是两位数代码,即使实际上是。
有什么建议吗?
试试这个:
trap -l | sed -nr 's/^([^0-9]*|.*[ \t])([0-9]+)\) SIGURG.*$//p'
现在一切正常。
加埃塔诺
更新:我找到了一个。 关于 sed
版本和编写可移植 sed
命令之间的差异,某些人可能仍然对这个 答案感兴趣。
在以下情况下效果很好:
- 支持
-r
的 sed
实现可以启用对 扩展 正则表达式的支持。
bash
用于执行命令,因为sed
命令期望bash
[=20=的输出格式] builtin 使用 -l
选项生成。
- 平台的正则表达式库支持
\b
词边界断言。
这适用于 OP,但并非所有平台都满足这些要求,尤其是 BSD 类平台,包括 OSX。
警告:
- 如果您指定 (a) 完整 信号名称(例如,
SIGUSR1
与仅 SIGUSR
),则接受的解决方案只会明确工作(b) 不是 另一个 信号名称的子串(例如,SIGRTMAX
与 SIGRTMAX-1
)。
鉴于 扩展的 正则表达式的功能,在 sed -r
支持 \b
的平台上解决这个缺点并不难(这是 (非便携式)公认解决方案的修正版本):
trap -l | sed -nr 's/.*\b([0-9]+)\) SIGTSTP(\s.*|$)//p'
注意末尾的alternation (...|...
),它规定信号名称后跟白色space或线.
(请注意,同样使用 \b
时 not 一般工作,因为它会在 -
之前匹配, 是 某些信号名称的有效部分)。
这里是 (也是不可移植的)等同于 BSD 类平台的修改后的接受答案,包括 OSX:
trap -l | sed -nE 's/.*[[:<:]]([0-9]+)\) SIGTSTP([[:blank:]].*|$)//p'
请注意,虽然 -E
也启用 扩展的 正则表达式,但支持的特定风格 与 Linux 不同 ] 一:必须用[[:<:]]
代替\b
,用[[:blank:]]
代替\s
。
遗憾的是,POSIX BREs (basic regular expressions) 的限制不允许交替,而使用 sed
可移植地将一个限制为 BRE。
因此,来自 amended 命令的 extended 正则表达式不能直接用符合 POSIX 的 BRE。
(请注意,GNU sed
确实 支持 BRE 中的交替,但这是一个不兼容的 扩展 .)
这是一个稳健、便携的解决方案,应该可以在任何POSIX兼容的平台上使用bash
;它采用了一种无法使用正则表达式替换的解决方法:
trap -l |
sed -n 's/^/ /; s/$/ /; s/.*[[:blank:]]\([0-9]\{1,\}\)) SIGTSTP[[:blank:]].*//p'
s/^/ /; s/$/ /
简单地在每一行前面和附加一个 space 字符,这样每个信号编号和信号名称都保证由 space 分隔,这简化了匹配。
- 请注意,由于必须使用 basic 正则表达式,特殊字符。例如
(
和 {
需要 转义 .
- POSIX 个字符。必须使用 类 等
[[:blank:]]
代替 \s
. 等快捷方式
- 重复符号
+
必须用 \{1,\}
模拟。
但是请注意,该解决方案本身不 POSIX 兼容:
trap
是bash
中的builtin,所以它的trap -l
输出格式和一样[=188] =] 在 所有 平台上 bash
运行s - 但请注意 bash
本身,而 POSIX-compatible,并非由 POSIX 本身强制执行,并且实现了 POSIX 标准的许多 扩展 - trap -l
是其中之一他们。
上面的命令依赖于 bash
的 trap -l
输出格式,如问题所示。
POSIX兼容性说明:
POSIX trap
builtin does NOT support -l
, whereas the POSIX kill
utility可以,但它规定了不同的格式:
"当指定-l
选项时,每个信号的符号名称应按以下格式书写:"%s%c", <signal_name>, <separator>
,其中<signal_name>
为大写,没有SIG
前缀,<separator>
应为 <newline>
或 <space>
。对于写入的最后一个信号,<separator>
应为 <newline>
- http://man.cx/kill;
例如:HUP INT QUIT ILL ...
规范没有强制要求列出信号的 order,但在实践中,实现似乎按数值的升序列出它们。
然而,bash
也有一个 kill
builtin,其 -l
选项产生 与trap -l
相同 输出。内置优先于实用程序,因此 bash
kill
内置隐藏外部 kill
实用程序。因此,kill -l
(和 trap -l
)在 bash
中产生的输出偏离了 POSIX 规定的格式,如下所示:
- 信号名称以它们的编号为前缀,格式为
<number>)
,后跟space
- 信号名称 具有
SIG
名称前缀。
因此,bash
的 kill -l
输出主动不符合 POSIX 标准,除非您 运行 bash
在 POSIX 模式(例如,通过 运行ning shopt -so posix
)。相比之下,ksh
、zsh
和 dash
中的 kill
默认符合 POSIX 规定的输出格式 .
尝试用单词边界限制匹配:
trap -l | sed -nr 's/.*\b([0-9]+)\) SIGTSTP.*//p'
这对目标字符串和 SIGPIPE [对我而言] 测试正确。
在bash
、ksh
或zsh
[=92中通过信号名称获取信号编号=],你可以简单地使用:
kill -l TSTP # -> e.g., 18 - case doesn't matter, but do not use the "SIG" prefix
因为它使用 kill
内置 (相对于外部实用程序版本,/bin/kill
),这个 应该可以工作在任何支持这些 shell 的平台上.
这是一个 POSIX 兼容的解决方案,它不依赖于特定的 shell:
/bin/kill -l | tr -s '[:blank:]' '\n' |
awk -v name='TSTP' 'toupper([=11=]) == toupper(name) {print NR}' # don't use "SIG" prefix
- external
kill
实用程序 /bin/kill
与 -l
选项一起用于列出信号。虽然 POSIX spec for kill
规定了一种输出格式,但它并不强制以特定顺序列出信号。然而,有意义的顺序是根据它们的数值,在实践中似乎是这样,这种方法依赖于它。
- 需要注意的是
/bin/kill
- 与 bash、ksh、zsh 和 dash 中的 kill
内置函数不同 - 不会通过 [= 报告信号 SIGRTMIN
25=] 在 Linux.
至于反向操作-通过其数字[=获得信号名称 94=] - 使用kill -l <number>
,例如:
kill -l 18 # -> e.g., 'TSTP'
bash
、ksh
、zsh
和 dash
中的 kill
内建函数都支持这个。
外部 /bin/kill
实现与上述 语法 不同:
macOS, GNU kill
: 以上形式有效。
procps-ng kill
,在 18.04 或以下 中出现在 Ubuntu,例如:仅接受
kill -l18
(或kill --list=18
);也就是说,选项参数必须直接附加到-l
选项,这是符合POSIX的语法,假设信号编号是可选选项参数(-l
本身列出所有信号名称);请参阅 POSIX utility argument syntax.
不幸的是,上面列出的其他实现 仅 支持 - 可能不明确 - -l 18
形式。
Ubuntu19.10(procps-ng 3.3.15)自带的procps-ng版本支持两种形式(还有 --list 18
)。向 jarno 致敬以求他的帮助。
我要陷阱信号SIGTSTP
,就这么简单:
trap "" SIGTSTP
然而,纯shell(sh
)不支持信号名称,因此陷阱必须使用信号编号代替,如下所示:
trap "" 20
问题:信号编号是 OS 相关的,所以 SIGTSTP 在 Linux 中是 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
,因为我需要的功能 --only-matching
并不总是受支持。 trap -l | grep -oE "[0-9]+\) SIGTSTP" | cut -d')' -f1
效果很好,但只适用于 Linux.
我也因为here
描述的贪心问题而使用sed
失败
所以trap -l | sed -nr 's/.*([0-9]+)\) SIGTSTP.*//p'
只有returns8
,没有18
我想让提取尽可能通用,所以我不会假设 SIGTSTP
是两位数代码,即使实际上是。
有什么建议吗?
试试这个:
trap -l | sed -nr 's/^([^0-9]*|.*[ \t])([0-9]+)\) SIGURG.*$//p'
现在一切正常。
加埃塔诺
更新:我找到了一个sed
版本和编写可移植 sed
命令之间的差异,某些人可能仍然对这个 答案感兴趣。
- 支持
-r
的sed
实现可以启用对 扩展 正则表达式的支持。 bash
用于执行命令,因为sed
命令期望bash
[=20=的输出格式] builtin 使用-l
选项生成。- 平台的正则表达式库支持
\b
词边界断言。
这适用于 OP,但并非所有平台都满足这些要求,尤其是 BSD 类平台,包括 OSX。
警告:
- 如果您指定 (a) 完整 信号名称(例如,
SIGUSR1
与仅SIGUSR
),则接受的解决方案只会明确工作(b) 不是 另一个 信号名称的子串(例如,SIGRTMAX
与SIGRTMAX-1
)。
鉴于 扩展的 正则表达式的功能,在 sed -r
支持 \b
的平台上解决这个缺点并不难(这是 (非便携式)公认解决方案的修正版本):
trap -l | sed -nr 's/.*\b([0-9]+)\) SIGTSTP(\s.*|$)//p'
注意末尾的alternation (...|...
),它规定信号名称后跟白色space或线.
(请注意,同样使用 \b
时 not 一般工作,因为它会在 -
之前匹配, 是 某些信号名称的有效部分)。
这里是 (也是不可移植的)等同于 BSD 类平台的修改后的接受答案,包括 OSX:
trap -l | sed -nE 's/.*[[:<:]]([0-9]+)\) SIGTSTP([[:blank:]].*|$)//p'
请注意,虽然 -E
也启用 扩展的 正则表达式,但支持的特定风格 与 Linux 不同 ] 一:必须用[[:<:]]
代替\b
,用[[:blank:]]
代替\s
。
遗憾的是,POSIX BREs (basic regular expressions) 的限制不允许交替,而使用 sed
可移植地将一个限制为 BRE。
因此,来自 amended 命令的 extended 正则表达式不能直接用符合 POSIX 的 BRE。
(请注意,GNU sed
确实 支持 BRE 中的交替,但这是一个不兼容的 扩展 .)
这是一个稳健、便携的解决方案,应该可以在任何POSIX兼容的平台上使用bash
;它采用了一种无法使用正则表达式替换的解决方法:
trap -l |
sed -n 's/^/ /; s/$/ /; s/.*[[:blank:]]\([0-9]\{1,\}\)) SIGTSTP[[:blank:]].*//p'
s/^/ /; s/$/ /
简单地在每一行前面和附加一个 space 字符,这样每个信号编号和信号名称都保证由 space 分隔,这简化了匹配。- 请注意,由于必须使用 basic 正则表达式,特殊字符。例如
(
和{
需要 转义 . - POSIX 个字符。必须使用 类 等
[[:blank:]]
代替\s
. 等快捷方式
- 重复符号
+
必须用\{1,\}
模拟。
但是请注意,该解决方案本身不 POSIX 兼容:
trap
是bash
中的builtin,所以它的trap -l
输出格式和一样[=188] =] 在 所有 平台上bash
运行s - 但请注意bash
本身,而 POSIX-compatible,并非由 POSIX 本身强制执行,并且实现了 POSIX 标准的许多 扩展 -trap -l
是其中之一他们。
上面的命令依赖于bash
的trap -l
输出格式,如问题所示。
POSIX兼容性说明:
POSIX
trap
builtin does NOT support-l
, whereas the POSIXkill
utility可以,但它规定了不同的格式:
"当指定-l
选项时,每个信号的符号名称应按以下格式书写:"%s%c", <signal_name>, <separator>
,其中<signal_name>
为大写,没有SIG
前缀,<separator>
应为<newline>
或<space>
。对于写入的最后一个信号,<separator>
应为<newline>
- http://man.cx/kill;
例如:HUP INT QUIT ILL ...
规范没有强制要求列出信号的 order,但在实践中,实现似乎按数值的升序列出它们。然而,
bash
也有一个kill
builtin,其-l
选项产生 与trap -l
相同 输出。内置优先于实用程序,因此bash
kill
内置隐藏外部kill
实用程序。因此,kill -l
(和trap -l
)在bash
中产生的输出偏离了 POSIX 规定的格式,如下所示:- 信号名称以它们的编号为前缀,格式为
<number>)
,后跟space - 信号名称 具有
SIG
名称前缀。
- 信号名称以它们的编号为前缀,格式为
因此,
bash
的kill -l
输出主动不符合 POSIX 标准,除非您 运行bash
在 POSIX 模式(例如,通过 运行ningshopt -so posix
)。相比之下,ksh
、zsh
和dash
中的kill
默认符合 POSIX 规定的输出格式 .
尝试用单词边界限制匹配:
trap -l | sed -nr 's/.*\b([0-9]+)\) SIGTSTP.*//p'
这对目标字符串和 SIGPIPE [对我而言] 测试正确。
在bash
、ksh
或zsh
[=92中通过信号名称获取信号编号=],你可以简单地使用:
kill -l TSTP # -> e.g., 18 - case doesn't matter, but do not use the "SIG" prefix
因为它使用 kill
内置 (相对于外部实用程序版本,/bin/kill
),这个 应该可以工作在任何支持这些 shell 的平台上.
这是一个 POSIX 兼容的解决方案,它不依赖于特定的 shell:
/bin/kill -l | tr -s '[:blank:]' '\n' |
awk -v name='TSTP' 'toupper([=11=]) == toupper(name) {print NR}' # don't use "SIG" prefix
- external
kill
实用程序/bin/kill
与-l
选项一起用于列出信号。虽然 POSIX spec forkill
规定了一种输出格式,但它并不强制以特定顺序列出信号。然而,有意义的顺序是根据它们的数值,在实践中似乎是这样,这种方法依赖于它。 - 需要注意的是
/bin/kill
- 与 bash、ksh、zsh 和 dash 中的kill
内置函数不同 - 不会通过 [= 报告信号SIGRTMIN
25=] 在 Linux.
至于反向操作-通过其数字[=获得信号名称 94=] - 使用kill -l <number>
,例如:
kill -l 18 # -> e.g., 'TSTP'
bash
、ksh
、zsh
和 dash
中的 kill
内建函数都支持这个。
外部 /bin/kill
实现与上述 语法 不同:
macOS, GNU
kill
: 以上形式有效。procps-ng
kill
,在 18.04 或以下 中出现在 Ubuntu,例如:仅接受
kill -l18
(或kill --list=18
);也就是说,选项参数必须直接附加到-l
选项,这是符合POSIX的语法,假设信号编号是可选选项参数(-l
本身列出所有信号名称);请参阅 POSIX utility argument syntax.
不幸的是,上面列出的其他实现 仅 支持 - 可能不明确 - -l 18
形式。
Ubuntu19.10(procps-ng 3.3.15)自带的procps-ng版本支持两种形式(还有 --list 18
)。向 jarno 致敬以求他的帮助。