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.just
    SIGUSR
    )即(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'