Unix / Linux - 信号和陷阱
-
简述
本章,我们将详细讨论 Unix 中的信号和陷阱。信号是发送到程序的软件中断,用于指示发生了重要事件。事件可以从用户请求到非法内存访问错误。一些信号,例如中断信号,表明用户要求程序做一些不在通常控制流程中的事情。下表列出了您可能会遇到并希望在您的程序中使用的常见信号 -信号名称 信号编号 描述 SIGHUP 1 检测到控制终端挂断或控制进程死亡 SIGINT 2 在用户发送中断信号时发出 (Ctrl + C) SIGQUIT 3 当用户发送退出信号时发出 (Ctrl + D) SIGFPE 8 如果尝试进行非法数学运算时发出 SIGKILL 9 如果进程收到此信号,它必须立即退出并且不会执行任何清理操作 SIGALRM 14 闹钟信号(用于定时器) SIGTERM 15 软件终止信号(默认由kill发送) -
信号列表
有一种简单的方法可以列出系统支持的所有信号。只需发出kill -l 命令,它将显示所有支持的信号 -信号的实际列表在 Solaris、HP-UX 和 Linux 之间有所不同。 -
默认操作
每个信号都有一个与之关联的默认操作。信号的默认操作是脚本或程序在收到信号时执行的操作。一些可能的默认操作是 --
终止进程。
-
忽略信号。
-
转储核心。这将创建一个名为core 包含进程收到信号时的内存映像。
-
停止进程。
-
继续停止的进程。
-
-
发送信号
有多种向程序或脚本传递信号的方法。最常见的一种是让用户键入CONTROL -C 或者 INTERRUPT key 当脚本正在执行时。当你按下 Ctrl+C 关键,一个 SIGINT 发送到脚本并根据定义的默认操作脚本终止。传递信号的另一种常用方法是使用 kill command,其语法如下 -这里 signal 是要传递的信号的编号或名称,并且 pid是信号应发送到的进程 ID。例如 -上述命令向正在运行的程序发送 HUP 或挂断信号 process ID 1001. 要向同一进程发送终止信号,请使用以下命令 -这会杀死正在运行的进程 process ID 1001. -
捕获信号
当您在执行 shell 程序期间在终端上按Ctrl+C或 Break 键时,通常该程序会立即终止,并且您的命令提示符会返回。这可能并不总是可取的。例如,您最终可能会留下一堆无法清理的临时文件。捕获这些信号非常容易,并且 trap 命令具有以下语法 -这里command可以是任何有效的 Unix 命令,甚至是用户定义的函数,并且 signal 可以是您想要捕获的任意数量信号的列表。shell 脚本中的 trap 有两种常见用途 -- 清理临时文件
- 忽略信号
-
清理临时文件
作为 trap 命令的示例,以下显示了如何删除一些文件,然后在有人试图从终端中止程序时退出 -从 shell 程序中执行此陷阱的点来看,这两个文件 work1$$ 和 dataout$$ 如果程序接收到第 2 号信号,将被自动删除。因此,如果用户在执行此陷阱后中断程序的执行,您可以放心,这两个文件将被清除。这exit 跟随的命令 rm 是必要的,因为没有它,程序将在接收到信号时停止的点继续执行。信号编号 1 是为 hangup. 要么有人故意挂断线路,要么线路意外断开。在这种情况下,您可以修改前面的陷阱以通过将信号编号 1 添加到信号列表中来删除两个指定的文件 -现在,如果线路挂断或按下Ctrl+C键,这些文件将被删除。如果指定给 trap 的命令包含多个命令,则必须用引号括起来。另请注意,shell 会在执行 trap 命令时以及在接收到列出的信号之一时扫描命令行。因此,在前面的示例中,值 WORKDIR 和 $$将在执行陷阱命令时被替换。如果您希望在接收到信号 1 或 2 时发生这种替换,您可以将命令放在单引号内 - -
忽略信号
如果为陷阱列出的命令为空,则接收时将忽略指定的信号。例如,命令 -这指定中断信号将被忽略。在执行不想被中断的操作时,您可能希望忽略某些信号。您可以指定多个要忽略的信号,如下所示 -请注意,必须为要忽略的信号指定第一个参数,并且不等同于编写以下内容,其具有单独的含义 -如果您忽略一个信号,则所有子 shell 也会忽略该信号。但是,如果您指定在接收到信号时要采取的操作,则所有子 shell 仍将在接收到该信号时采取默认操作。 -
重置陷阱
在您更改了接收信号时要采取的默认操作后,如果您只是省略第一个参数,则可以使用陷阱再次将其更改回来;所以 -这会将在接收到信号 1 或 2 时采取的操作重置为默认值。