shell学习五十三天----捕获信号trap

捕捉进程信号

信号是一种进程间的通信机制,它给应用程序提供一种异步的软件中断,是应用程序有机会接受其他程序活终端发送的命令(即信号).应用程序收到信号后,有三种处理方式:忽略,默认,捕捉.该进程收到一个信号后,会检查对该信号的处理机制.如果是SIG_IGN,就会忽略该信号;如果是SIG_DFT,则会采用系统默认的处理动作,通常是终止进程或忽略该信号;如果给该信号指定了一个处理函数(捕捉),则会中断当前进程正在执行的任务,转而去执行该信号的处理函数,返回后在继续执行被中断的任务.

 

在有些情况下,我们不希望自己的shell脚本在运行时刻被中断,比如说我们写的shell脚本设为某一用户的默认shell,使这一用户进入系统后只能做某一项工作,如数据库备份,我们可不希望用户使用Ctrl+C键便能进入到shell状态,做我们不希望看到的事情,这便用到了信号处理.

 

以下是一些常见的信号:

信号名称

信号数

说明

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缺省产生这个信号。 

 

 

捕获信号

当按下了Ctrl+C键或break键在终端一个shell程序的执行过程中,正常程序将立即终止,并返回命令提示符.这可能并使总是可取的,例如,你可能最终留下了一堆临时文件,将不会清理.

捕获这些信号是很容易的,trap命令的语法如下:

#trap commands signals

这里的commands可以是任何有效的linux命令,或一个用户定义的函数,信号可以是任意数量的信号,你想来捕获的列表.

 

一. trap捕捉到信号之后,可以有三种反应方式:
  (1)执行一段程序来处理这一信号
  (2)接受信号的默认操作
  (3)忽视这一信号

. trap对上面三种方式提供了三种基本形式:
  第一种形式的trap命令在shell接收到signal list清单中数值相同的信号时,将执行双
引号中的命令串。
  trap 'commands' signal-list
  trap "commands" signal-list
为了恢复信号的默认操作,使用第二种形式的trap命令:
  trap signal-list
第三种形式的trap命令允许忽视信号
  trap " " signal-list
注意:
  (1) 对信号11(段违例)不能捕捉,因为shell本身需要捕捉该信号去进行内存的转储。
  (2) trap中可以定义对信号0的处理(实际上没有这个信号), shell程序在其终止(如执行exit语句)时发出该信号。
  (3) 在捕捉到signal-list中指定的信号并执行完相应的命令之后, 如果这些命令没有将shell程序终止的话,shell程序将继续执行收到信号时所执行的命令后面的命令,这样将很容易导致shell程序无法终止。另外,在trap语句中,单引号和双引号是不同的,当shell程序第一次碰到trap语句时,将把commands中的命令扫描一遍。此时若commands是用单引号括起来的话,那么shell不会对commands中的变量和命令进行替换, 否则commands中的变量和命令将用当时具体的值来替换.

trap命令用于指定在接收到信号后将要采取的动作.常见的用途是在脚本程序被中断时完成清理工作.

 

测试案例:

按照用户的要求,我们需要屏蔽的是HUP INT QUIT TSTP几个信号.所以,可以运行:

#trap “”HUP INT QUIT TSTP

这个时候,可以试试打开一个持续的命令,然后中断其运行,例如:

#tail -f /var/log/messages

接着,试试用Ctrl+CCtrl+\来中断试试,该进程是不会退出的.

 

恢复信号

如果想恢复的话,可以用Ctrl+Z吧进程放到后台,然后运行:

#trap : HUP INT QUIT TSTP

然后,#ps -ef看看其PID,bg 1让程序继续运行,最后用kill杀掉即可.

 

 

其他

可以试试运行:

#trap “echo ‘hello world’” HUP INT QUIT TSTP

这样,当你运行Ctrl+C等中断时,会自动运行echo命令,结果就是实现helloworld字符串:

引用

#tail -f /var/log/messages

 

注意,这方式并不能屏蔽中断,按下Ctrl+C键仍然会退出程序,仅会再运行一个额外的命令而已.

你可能感兴趣的:(shell)