Unix / Linux - Signals and Traps

在本章中,我们将详细讨论Unix中的信号和陷阱.

信号是发送到程序的软件中断,表示发生了重要事件.事件可能因用户请求到非法内存访问错误而异.某些信号(例如中断信号)表示用户已要求程序执行一些不在通常控制流程中的操作.

下表列出了可能的常见信号遇到并希望在你的程序中使用 :

<td style ="text-align:center ;>> SIGINT

信号名称信号编号描述
SIGHUP1在控制终端上检测到挂断或控制进程死亡
SIGINT    2如果用户发送中断信号,则发出(Ctrl + C)
SIGQUIT3如果发出用户发送退出信号(Ctrl + D)
SIGFPE8如果非法数学运算是尝试
SIGKILL9如果进程收到此信号,它必须立即退出并且不会执行任何清理 - 上升操作
SIGALRM14闹钟信号(用于计时器)
SIGTERM15软件终止信号(默认情况下由kill发送)

信号列表

有一种简单的方法可以列出系统支持的所有信号.只需发出 kill -l 命令,它就会显示所有支持的信号 :

$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
 9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGSTKFLT
17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU
25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH
29) SIGIO       30) SIGPWR      31) SIGSYS      34) SIGRTMIN
35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4
39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6
59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

实际的信号列表因Solaris,HP-UX和Linux而异.

默认操作

每个信号都有一个与之关联的默认操作.信号的默认操作是脚本或程序在收到信号时执行的操作.

一些可能的默认操作是 :

  • 终止流程.

  • 忽略信号.

  • 转储核心.这将创建一个名为 core 的文件,其中包含进程收到信号时的内存映像.

  • 停止进程.

  • 继续停止流程.

发送信号

有几种方法可以向程序或脚本传递信号.其中一个最常见的是用户在脚本执行时键入 CONTROL-C INTERRUPT键.

Ctrl + C 键, SIGINT 将被发送到脚本,并根据定义的默认操作脚本终止.

传递信号的另一种常用方法是使用 kill命令,其语法如下 :

 $ kill -signal pid

这里信号是要传递的信号的数量或名称和 pid 是信号应发送到的进程ID.例如 :

 $ kill -1 1001

以上命令将HUP或挂断信号发送到使用进程ID 1001 运行的程序.要向同一进程发送终止信号,请使用以下命令 :

$ kill -9 1001

这会使进程ID 1001 终止运行.

陷阱信号

在执行shell程序期间按终端上的 Ctrl + C 或Break键,通常会立即终止该程序,并返回命令提示符.这可能并不总是令人满意的.例如,您最终可能会留下一堆无法清理的临时文件.

捕获这些信号非常简单,并且trap命令具有以下语法 :

$ trap命令信号

这里命令可以是任何有效的Unix命令,甚至是用户定义的函数,信号可以是要捕获的任意数量信号的列表.

陷阱有两种常见用途在shell脚本中 :

  • 清理临时文件

  • 忽略信号

清理临时文件

作为trap命令的示例,下面显示了如何删除某些文件然后退出if有人试图从终端中止程序 :

$ trap "rm -f $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 2

从shell程序中的那一点开始执行此陷阱,如果信号编号,将自动删除两个文件 work1 $$ dataout $$ 程序收到2.

因此,如果用户在执行此陷阱后中断执行程序,则可以确保清除这两个文件. rm 之后的退出命令是必要的,因为没有它,执行将在程序中在接收到信号时停止的位置继续执行.

挂断生成信号编号1.有人故意挂断线路或线路意外断开.

您可以修改前面的陷阱,在这种情况下也删除两个指定的文件,方法是在信号列表中添加1号信号. signal :

$ trap "rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 1 2

如果线路挂断或按下 Ctrl + C 键,这些文件将被删除.

指定为trap的命令必须用引号括起来,如果它们包含多个命令.另请注意,shell在执行trap命令时以及在收到列出的信号之一时扫描命令行.

因此,在前面的示例中,值为 WORKDIR $$ 将在执行trap命令时被替换.如果您希望在收到信号1或2时发生此替换,您可以将命令放在单引号和减号内;

$ trap 'rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit' 1 2

忽略信号

如果为trap列出的命令为null,则忽略指定的信号收到的时候.例如,命令 :

 $ trap''2

这指定要忽略中断信号.在执行不希望被中断的操作时,您可能希望忽略某些信号.您可以指定多个要忽略的信号,如下所示;

 $ trap''1 2 3 15

请注意,必须为要忽略的信号指定第一个参数,并且不等于编写以下内容,该参数具有其自身和减号的单独含义;

 $ trap 2

如果忽略一个信号,所有子shell也会忽略该信号.但是,如果您指定在收到信号时要采取的操作,则所有子壳仍将在收到该信号时采取默认操作.

重置陷阱

在您更改了接收信号时要执行的默认操作后,如果您只是省略第一个参数,则可以使用陷阱再次将其更改回来; so :

 $ trap 1 2

这会重置动作收到信号1或2后返回默认值.