15.1-处理信号

Linux使用信号与系统上运行的进程进行通信。
可以使用这些信号控制Shell脚本的运行,只需要让shell脚本在接收到来自Linux系统的特定信号时执行命令即可。

1. 常用的Linux信号

编号

信号名称

缺省操作

解释

POSIX

1

SIGHUP

Terminate

挂起控制终端或进程

2

SIGINT

Terminate

来自键盘的中断

3

SIGQUIT

Dump

从键盘退出

4

SIGILL

Dump

非法指令

5

SIGTRAP

Dump

跟踪的断点

6

SIGABRT

Dump

异常结束

6

SIGIOT

Dump

等价于SIGABRT

7

SIGBUS

Dump

总线错误

8

SIGFPE

Dump

浮点异常

9

SIGKILL

Terminate

强迫进程终止

10

SIGUSR1

Terminate

对进程可用

11

SIGSEGV

Dump

无效的内存引用

12

SIGUSR2

Terminate

对进程可用

13

SIGPIPE

Terminate

向无读者的管道写

14

SIGALRM

Terminate

实时定时器时钟

15

SIGTERM

Terminate

进程终止

16

SIGSTKFLT

Terminate

协处理器栈错误

17

SIGCHLD

Ignore

子进程停止、结束或在被跟踪时获得信号

18

SIGCONT

Continue

如果已停止则恢复执行

19

SIGSTOP

Stop

停止进程执行

20

SIGTSTP

Stop

从tty发出停止进程

21

SIGTTIN

Stop

后台进程请求输入

22

SIGTTOU

Stop

后台进程请求输出

23

SIGURG

Ignore

套接字上的紧急条件

24

SIGXCPU

Dump

超过CPU时限

25

SIGXFSZ

Dump

超过文件大小的限制

26

SIGVTALRM

Terminate

虚拟定时器时钟

27

SIGPROF

Terminate

概况定时器时钟

28

SIGWINCH

Ignore

窗口调整大小

29

SIGIO

Terminate

I/O现在可能发生

29

SIGPOLL

Terminate

等价于SIGIO

30

SIGPWR

Terminate

电源供给失败

31

SIGSYS

Dump

坏的系统调用

31

SIGUNUSED

Dump

等价于SIGSYS

  • 默认情况下,bash shell会忽略它接收的任何SIGQUIT信号、SIGTERM信号(以防止交互的shell意外终止)。但是,bashshell处理它收到的任何SIGHUP、SIGINT信号。
  • 如果bash shell收到一个SIGHUP信号,它会退出。在退出之前,它将SIGHUP信号传递给shell启动的任意进程(如shell脚本)。收到SIGINT信号,shell会立即中断。Linux内核停止向shell提供CPU 上的处理时间。这种情况下,shell将SIGINT信号传递给由shell启动的人任意进程以通知它们这种情况。
  • 默认的shell脚本行为将忽略这些信号,这样会对脚本运行产生不良影响。为避免这种情况发生,对脚本进行编程以识别信号,并执行命令以便脚本为信号结果做好准备。

2. 生成信号

 Bashshell可以使用键盘上的组合键生成两个基本的Linux信号。如果需要停止或暂停失控的程序,那么这个功能会被用上。

2.1 中断进程

使用Ctrl+C组合键可以生成SIGINT信号,并将其发送给当前正在shell中运行的任意进程。运行一个通常需要很长时间才能完成的命令并按Ctrl+C组合键,可以测试此操作。
Ctrl+C组合键不会在监视器上生成任何输出,它只会停止当前在shell中运行的进程。sleep命令在指定的秒数之内暂停操作。
通常,命令提示符在计时器过期之前不会返回。在计时器过期之前按Ctrl+C组合键,可以使sleep命令提前终止。

 

自学Linux Shell15.1-处理信号_bash

2.2 暂停进程

Ctrl+Z组合键生成SIGSTP信号,可以停止任何在shell中运行的进程。停止进程与终止进程不同,停止进程后程序任然留在内存中,能够从停止的地方继续运行。

自学Linux Shell15.1-处理信号_shell脚本_02

方括号中的数字是shell分配的作业编号(jobnumber)
shell以作业(job)形式引用shell中运行的每个进程,向每个作业分配唯一的作业编号。
它向第一个启动的进程分配作业编号1,向第二进程分配作业编号2,以此类推。
如果shell会话中有一个停止的作业,在退出shell时bash将发出警告。使用ps命令查看停止的作业:

 

自学Linux Shell15.1-处理信号_bash_03

在S列(进程状态),ps命令将已停止作业的状态显示为T
如果想在停止作业仍处于活动状态时退出shell,只需要再次键入exit命令。shell将退出,并终止亭子的作业。还有一种方法是知道停止作业的PID,使用kill命令发送SIGKILL信号来终止它。

 

自学Linux Shell15.1-处理信号_shell脚本_04

2.3 捕获信号

除了可以使脚本忽略信号之外,还可以在信号出现时捕获信号和执行其他命令。
trap命令可以指定能够通过shell脚本监控和拦截的Linux信号。如果脚本收到trap命令中列出的信号,它将保护该信号不被shell处理,并在本地处理它。
trap命令格式:trap commands signals。在trap命令行中,只需要列出希望shell执行的命令,以及希望捕获的信号列表(以空格分隔)。指定信号可以通过它们的数值或Linux信号名实现。

 

自学Linux Shell15.1-处理信号_bash_05

当每次检测到SIGINT和SIGTERM信号时显示一个简单的文本消息。如果捕获到这些信号,在用户试图使用bash shell键盘Ctrl+C命令停止程序时,脚本将不受影响。每次使用Ctrl+C组合键时,脚本执行trap命令中指定的echo语句,而不是忽略信号并允许shell停止脚本。

2.4 捕获脚本退出   

除了在shell脚本中捕获信号之外,可以在shell脚本退出时捕获它们。这是一种在shell完成作业时执行命令的便捷方式。要捕获shell脚本退出,只需要向trap命令添加EXIT信号。   

自学Linux Shell15.1-处理信号_后台进程_06

当脚本到达常规退出点时,就会触发trap,shell将执行在trap命令行中指定的命令。
如果提前退出脚本,也能够捕获EXIT。使用Ctrl+C组合键发送SIGINT信号时,脚本退出,但是在脚本退出之前,shell将执行trap命令。

2.5 移除捕获

要移除捕获,使用破折号作为命令和想要恢复正常行为的信号列表。

 

自学Linux Shell15.1-处理信号_后台进程_07

信号捕获移除后,脚本将忽略信号。但是,如果在移除捕获之前收到信号,脚本仍将根据trap命令处理该信号。

3. 后台模式下运行脚本

使用ps命令,可以查看Linux系统上运行的进程。所有进程不在终端监视器上运行。这就是所谓的后台运行进程。在后台模式中,进程运行时与终端会话STDIN、STDOUT和STDERR无关。
通过命令行界面以后台模式运行shell界面,只需要在命令后加上一个&符号。将&符号放在命令之后时,它将bashshell与命令相分离,并以独立的后台进程形式在系统上运行。
         显示的一行类似:[1]  19555,方括号的数字是shell分配给后台的作业编号。后面的数字是LInux系统分配给进程的PID。所有Linux系统上运行的进程都必须有唯一的PID。
系统显示这些条目之后,将出现一个新的命令行界面提示符。执行的命令将以后模式安全运行。
这是,可以在提示符处输出新的命令,但是后台进程仍在运行,任然使用终端监视器显示STDOUT和STDERR消息。
后台进程结束时,在终端显示消息格式:[1]+ Done       ./test  这表示作业编号和作业状态(Done),以及用于启动该作业的命令。

 

自学Linux Shell15.1-处理信号_后台进程_08

可以通过命令行提示符同时启动任何数量的后台作业。每次启动一个新作业时,Linux系统将分配一个新作业编号和一个PID。使用ps命令可以查看运行的所有脚本。

启动的每个后台进程都出现在ps命令的运行进程输出列表中。如果所有进程都在终端会中显示输出,那会变成一团糟。

注意ps命令的输出,每个后台进程都连接着一个终端会话(pts/0)终端。如果终端会话退出,则后台进程将退出。如果与终端相关联的后台程序正在运行,有些终端模拟器会发出警告,而有些则不会。如果希望在注销控制台后脚本继续以后太模式运行,则需要执行一些其他操作。

4. 非控制台下运行脚本

有时需要从终端启动shell脚本,然后让脚本结束之前以后台模式运行,即使退出终端会话也是如此。
nohup命令运行另一个命令阻塞发送到进程的任何SIGHUP信号。这可以防止在退出终端会话时退出进程。
nohup命令格式:nohup test.sh &

nohupm命令将进程与终端断开,所以进程没有STDOUT和STDERR输出链接。为了接收命令生成的任何输出,nohup命令自动将STDOUT和STDERR消息冲向的到称为nohup.out的文件。nohup.out文件包含通常发送到终端监视器的所有输出。进程运行完成后,可以打开nohup.out文件查看输出结果。