信号捕捉
信号是一种进程间的通信机制,它给应用程序提供一种异步的软件中断,使应用程序有机会接受其他程序活终端发送的命令(即信号)。
应用程序收到信号后,有三种处理方式:忽略,默认,捕捉。进程收到一个信号后,会检查对该信号的处理机制。如果是 SIG_IGN,就忽略该信号;如果是 SIG_DFT,则会采用系统默认的处理动作,通常是终止进程或忽略该信号;如果给该信号指定了一个处理函数(捕捉),则会中断当前进程正在执行的任务,转而去执行该信号的处理函数,返回后再继续执行被中断的任务。
常见信号
kill -l
和 trap -l
可列出系统的信号
1 | [user1@study ~]$ kill -l |
stty -a
可列出中断信号与键盘的对应
1 | [user1@study ~]$ stty -a |
常见的信号及其描述
信号 | Num | 描述 |
---|---|---|
SIGHUP | 1 | 在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端不再关联。 登录Linux时,系统会分配给登录用户一个终端(Session)。在这个终端运行的所有程序,包括前台进程组和后台进程组,一般都属于这个Session。当用户退出Linux登录时,前台进程组和后台有对终端输出的进程将会收到SIGHUP信号。这个信号的默认操作为终止进程,因此前台进程组和后台有终端输出的进程就会中止。对于与终端脱离关系的守护进程,这个信号用于通知它重新读取配置文件。 |
SIGINT | 2 | 程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl C)时发出。 |
SIGQUIT | 3 | 和SIGINT类似, 但由QUIT字符(通常是Ctrl /)来控制. 进程在因收到SIGQUIT退出时会产生core文件, 在此意义上类似于一个程序错误信号。 |
SIGFPE | 8 | 在发生致命的算术运算错误时发出. 不仅包括浮点运算错误, 还包括溢出及除数为0等其它所有的算术的错误。 |
SIGKILL | 9 | 用来立即结束程序的运行. 本信号不能被阻塞, 处理和忽略。 |
SIGALRM | 14 | 时钟定时信号, 计算的是实际时间或时钟时间. alarm函数使用该信号。 |
SIGTERM | 15 | 程序结束(terminate)信号, 与SIGKILL不同的是该信号可以被阻塞和处理. 通常用来要求程序自己正常退出. shell命令kill缺省产生这个信号。 |
捕捉信号
在终端一个 shel l程序的执行过程中,按下 Ctrl
+ C
键正常程序将立即终止,并返回命令提示符。可能并不总是可取的。比如有可能最终产生临时文件,不会被清理。
Ctrl
+C
—> SIGINIT(2)Ctrl
+Z
—> SIGCONT(18)
使用 trap
命令可以捕捉信号并执行引号(但双引均可)中的命令串或函数
1 | # trap 'commands或functions' signal-list |
恢复信号的默认操作
1 | trap signal-list |
忽略信号
1 | trap " " signal-list |
注意事项
- 对信号SIGSEGV(11)不能捕捉,因为shell本身需要捕捉(该信号去进行内存的转储)
- 在脚本中可以捕捉信号,但无法捕捉KILL(9)和TERM(15)
- 在trap中可以定义对信号0的处理(实际上没有此信号),shell程序在其终止(如执行exit语句)时发出该信号
- 在捕捉到signal-list中指定的信号并执行完相应的命令之后, 如果这些命令没有将shell程序终止的话,shell程序将继续执行收到信号时所执行的命令后面的命令,这样将很容易导致shell程序无法终止。
通常需要忽略的四个信号HUP(1), INT(2), QUIT(3), TSTP(24)
1 | trap "" 1 2 3 24 |
使其恢复默认值
1 | trap :1 2 3 24 |