linux下trap命令和SIGHUP信号量详解

trap命令用于指定在接收到信号后将要采取的动作。常见的用途是在脚本程序被中断时完成清理工作。不过,这次我遇到它,是因为客户you个需求:从终端访问服务器的用户,其登陆服务器后会自动运行某个命令,例如打开应用(命令写在.bashrc等文件中),最后退出,并断开连接;期间是不能允许其使用Ctrl+C等中断退出应用,而回到Shell环境,否则可能会带来安全问题。

当然,解决de方式有很多,如在应用中屏蔽中断信号、使用chroot方式访问等。但这些方法都you一些限制,如需要修改应用,让telnet等支持chroot方式(ssh可支持chroot)等。而使用trap也是一种比较好的解决方法。

一、关于信号

  历史上,shell总是用数字来代表信号,而新de脚本程序应该使用信号de名字,它们保存在用#include命令包含进来designal.h头文件中,在使用信号名时需要省略SIG前缀。

  kill和trap等都可以看到信号编号及其关联de名称。“信号”是指那些被异步发送到一个程序de事件。默认情况下,它们通常会终止一个程序de运行。

引用

  # trap -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   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

  附录中有个说明文档。

二、trap de使用

  1、运行格式

  trap命令de参数分为两部分,前一部分是接收到指定信号时将要采取de行动,后一部分是要处理de信号名。

  trapcommand signal

  它you三种形式分别对应三种不同de信号回应方式。

  第一种:

  trap"commands" signal-list

  当脚本收到signal-list清单内列出de信号时,trap命令执行双引号中de命令。

  第二种:

  trap signal-list

  trap不指定任何命令,接受信号de默认操作,默认操作是结束进程de运行。

  第三种:

  trap " " signal-list

  trap命令指定一个空命令串,允许忽视信号,wo men 用到de就是这一种。

  ※ 请记住,脚本程序通常是以从上到下de顺序解释执行de,所以必须在你想保护de那部分代码以前指定trap命令。

  2、测试

  按照用户de要求,wo men 需要屏蔽de是HUP INTQUIT TSTP几个信号。所以,可以运行:

  # trap"" HUP INT QUIT TSTP

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

  # tail-f /var/log/messages

  接着,试试用Ctrl+C 或 Ctrl+\来中断试试,会程序是不会退出de。

  3、恢复信号

  如果想恢复de话,可以用Ctrl+Z把程序放到后台,然后运行:

  # trap: HUP INT QUIT TSTP

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

  4、其他

  您也可以试试运行:

  # trap "echo 'Hello World'" HUP INT QUIT TSTP

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

  引用

  # tail -f /var/log/messages

  May 18 16:57:54 192.168.228.153 dhcpd: DHCPREQUEST for192.168.228.221 from 00:1d:72:92:d4:68 via eth0

  May 18 16:57:54 192.168.228.153 dhcpd: DHCPACK on 192.168.228.221to 00:1d:72:92:d4:68 via eth0

  [root@mail ~]# Hello World

  ※ 注意,这方式并不能屏蔽中断,敲入Ctrl+C 等信息后,仍以默认行为动作de,也就是退出程序,仅会再运行一个额外de命令而已。

 三、附录

  1、中断按键

  不同de终端类型、Shell版本其中断de按键是不同de,甚至还可以自定义,这可通过stty命令查询:

  引用

  # stty -a

  speed 38400 baud; rows 30; columns 111; line = 0;

  intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = ;eol2 = ; start = ^Q; stop = ^S;

  susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min =1; time = 0;

  -parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts

  -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnlixon -ixoff -iuclc -ixany -imaxbel

  opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0tab0 bs0 vt0 ff0

  isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop-echoprt echoctl echoke

  ^就是Ctrlde缩写。

  2、信号详情

  引用

  名称     默认动作           说明

  SIGHUP     终止进程     终端线路挂断

  SIGINT   终止进程     中断进程

  SIGQUIT  建立CORE文件  终止进程,并且生成core文件

  SIGILL   建立CORE文件       非法指令

  SIGTRAP  建立CORE文件       跟踪自陷

  SIGBUS   建立CORE文件       总线错误

  SIGSEGV  建立CORE文件       段非法错误

  SIGFPE   建立CORE文件       浮点异常

  SIGIOT   建立CORE文件       执行I/O自陷

  SIGKILL  终止进程     杀死进程

  SIGPIPE  终止进程     向一个没you读进程de管道写数据

  SIGALarm 终止进程     计时器到时

  SIGTERM  终止进程     软件终止信号

  SIGSTOP  停止进程     非终端来de停止信号

  SIGTSTP  停止进程     终端来de停止信号

  SIGCONT  忽略信号     继续执行一个停止de进程

  SIGURG   忽略信号     I/O紧急信号

  SIGIO    忽略信号     描述符上可以进行I/O

  SIGCHLD  忽略信号     当子进程停止或退出时通知父进程

  SIGTTOU  停止进程     后台进程写终端

  SIGTTIN  停止进程     后台进程读终端

  SIGXGPU  终止进程     CPU时限超时

  SIGXFSZ  终止进程     文件长度过长

  SIGWINCH 忽略信号     窗口大小发生变化

  SIGPROF  终止进程     统计分布图用计时器到时

  SIGUSR1  终止进程     用户定义信号1

  SIGUSR2  终止进程     用户定义信号2

  SIGVTALRM终止进程     虚拟计时器到时

  1)SIGHUP 本信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端de控制进程结束时, 通知同一session内de各个作业, 这时它们与控制终端不再关联.

  2)SIGINT 程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出

  3)SIGQUIT 和SIGINT类似, 但由QUIT字符(通常是Ctrl-\)来控制. 进程在因收到SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信号.

  4)SIGILL 执行了非法指令. 通常是因为可执行文件本身出现错误, 或者试图执行数据段. 堆栈溢出时也you可能产生这个信号.

  5) SIGTRAP 由断点指令或其它trap指令产生. 由debugger使用.

  6) SIGABRT 程序自己发现错误并调用abort时产生.

  7) SIGIOT 在PDP-11上由iot指令产生, 在其它机器上和SIGABRT一样.

  8) SIGBUS 非法地址, 包括内存地址对齐(alignment)出错. eg: 访问一个四个字长de整数, 但其地址不是4de倍数.

  9)SIGFPE 在发生致命de算术运算错误时发出. 不仅包括浮点运算错误, 还包括溢出及除数为0等其它所youde算术de错误.

  10)SIGKILL 用来立即结束程序de运行. 本信号不能被阻塞, 处理和忽略.

  11)SIGUSR1 留给用户使用

  12)SIGSEGV 试图访问未分配给自己de内存, 或试图往没you写权限de内存地址写数据.

  13)SIGUSR2 留给用户使用

  14)SIGPIPE Broken pipe

  15)SIGALRM 时钟定时信号, 计算de是实际de时间或时钟时间. alarm函数使用该信号.

  16)SIGTERM 程序结束(terminate)信号, 与SIGKILL不同de是该信号可以被阻塞和处理. 通常用来要求程序自己正常退出. shell命令kill缺省产生这个信号.

  17) SIGCHLD子进程结束时, 父进程会收到这个信号.

  18)SIGCONT让一个停止(stopped)de进程继续执行. 本信号不能被阻塞. 可以用一个handler来让程序在由stopped状态变为继续执行时完成特定de工作. 例如, 重新显示提示符

 19) SIGSTOP 停止(stopped)进程de执行. 注意它和terminate以及interruptde区别: 该进程还未结束, 只是暂停执行. 本信号不能被阻塞, 处理或忽略.

  20) SIGTSTP 停止进程de运行, 但该信号可以被处理和忽略. 用户键入SUSP字符时(通常是Ctrl-Z)发出这个信号

  21) SIGTTIN 当后台作业要从用户终端读数据时, 该作业中de所you进程会收到SIGTTIN信号. 缺省时这些进程会停止执行.

  22)SIGTTOU 类似于SIGTTIN,但在写终端(或修改终端模式)时收到.

  23)SIGURG you紧急数据或out-of-band数据到达socket时产生.

  24)SIGXCPU 超过CPU时间资源限制. 这个限制可以由getrlimit/setrlimit来读取/改变

  25)SIGXFSZ 超过文件大小资源限制.

  26)SIGVTALRM 虚拟时钟信号. 类似于SIGALRM,但是计算de是该进程占用deCPU时间.

  27)SIGPROF 类似于SIGALRM/SIGVTALRM,但包括该进程用deCPU时间以及系统调用de时间.

  28)SIGWINCH 窗口大小改变时发出.

  29)SIGIO 文件描述符准备就绪, 可以开始进行输入/输出操作.

  30) SIGPWR Power failure

  对于2和3信号量好理解,屏蔽ctrl+c和ctrl+\。但是1信号量到底什么作用呢?

  转自http://blog.csdn.net/cugxueyu/archive/2008/01/16/2046565.aspx

  SIGHUP信号与控制终端

  UNIX中进程组织结构为session (会话)包含一个前台进程组及一个或多个后台进程组,一个进程组包含多个进程。一个session可能会you一个session首进程,而一个session首进程可能会you一个控制终端。一个进程组可能会you一个进程组首进程。进程组首进程de进程ID与该进程组ID相等。这儿是可能会you,在一定情况之下是没youde。与终端交互de进程是前台进程,否则便是后台进程。

  SIGHUP会在以下3种情况下被发送给相应de进程:

  1、终端关闭时,该信号被发送到session首进程以及作为job提交de进程(即用 & 符号提交de进程)

  2、session首进程退出时,该信号被发送到该session中de前台进程组中de每一个进程

  3、若父进程退出导致进程组成为孤儿进程组,且该进程组中you进程处于停止状态(收到SIGSTOP或SIGTSTP信号),该信号会被发送到该进程组中de每一个进程。

  系统对SIGHUP信号de默认处理是终止收到该信号de进程。所以若程序中没you捕捉该信号,当收到该信号时,进程就会退出。

  下面观察几种因终端关闭导致进程退出de情况,在这儿进程退出是因为收到了SIGHUP信号。loginshell是session首进程。

  首先写一个测试程序,代码如下:

  #include<stdio.h>

  #include<signal.h>

  char**args;

  void exithandle(int sig)

  ...{

  printf("%s : sighup received ",args.);

  }

  int main(int argc,char **argv)

  ...{

  args = argv;

  signal(SIGHUP,exithandle);

  pause();

  return 0;

  }

  程序中捕捉SIGHUP信号后打印一条信息,pause()使程序暂停。

  编译后de执行文件为sigtest。

  1、命 令:sigtest front > tt.txt

  操 作:关闭终端

  结 果:tt.txt文件de内容为front : sighup received

  原 因: sigtest是前台进程,终端关闭后,根据上面提到de第1种情况,login shell作为session首进程,会收到SIGHUP信号然后退出。根据第2种情况,sigtest作为前台进程,会收到login shell发出deSIGHUP信号。

  2、命 令:sigtest back > tt.txt &

  操 作:关闭终端

  结 果:tt.txt文件de内容为 back : sighup received

  原 因: sigtest是提交dejob,根据上面提到de第1种情况,sigtest会收到SIGHUP信号。

  3、命 令:写一个shell,内容为[sigtest&],然后执行该shell

  操 作:关闭终端

  结 果:ps -ef| grep sigtest 会看到该进程还在,tt文件为空

  原 因: 执行该shell时,sigtest作为job提交,然后该shell退出,致使sigtest变成了孤儿进程,不再是当前sessiondejob了,因此sigtest即不是session首进程也不是job,不会收到SIGHUP。同时孤儿进程属于后台进程,因此loginshell退出后不会发送SIGHUP给sigtest,因为它只将该信号发送给前台进程。第3条说过若进程组变成孤儿进程组de时候,若you进程处于停止状态,也会收到SIGHUP信号,但sigtest没you处于停止状态,所以不会收到SIGHUP信号。

  4、命 令:nohup sigtest > tt

  操 作:关闭终端

  结 果:tt文件为空

  原 因: nohup可以防止进程收到SIGHUP信号

  至此,wo men 就清楚了何种情况下终端关闭后进程会退出,何种情况下不会退出。

  要想终端关闭后进程不退出you以下几种方法,均为通过shellde方式:

  1、编写shell,内容如下

  trap"" SIGHUP #该句de作用是屏蔽SIGHUP信号,trap可以屏蔽很多信号

  sigtest

  2、nohupsigtest 可以直接在命令行执行,

  若想做完该操作后继续别de操作,可以 nohupsigtest &

  3、编写shell,内容如下

  sigtest&

  其实任何将进程变为孤儿进程de方式都可以,包括fork后父进程马上退出。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值