前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >bash 中冷门但非常有用的命令: trap

bash 中冷门但非常有用的命令: trap

作者头像
qsjs
发布2020-06-09 10:41:24
4.7K0
发布2020-06-09 10:41:24
举报

trap 属于bash的内置命令,所以查看帮助用: help trap, 如果用”man trap“则会跳出bash的帮助文档; trap命令的作用是:对捕获到的SIGNAL ,改变原有的处理action为新的action; A. 支持哪些信号呢? trap -l 可以列出所有支持的signal.

代码语言:javascript
复制
[root@www ~]# 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
16) SIGSTKFLT   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    
[root@www ~]# 

B. 如何使用trap来更改原来SIGNAL对应的action? 语法格式: trap COMMAND SIGNAL_DEFINATION

看下面的例子:
代码语言:javascript
复制
[root@www ~]# trap 'echo -e "\nCTRL_C PRESSED"' SIGINT
[root@www ~]# ^C       #此处是同时按下: CTRL+C 的结果,并不是输入^C 
CTRL_C PRESSED

[root@www ~]# 

上面例子就是捕获CTRL+C, 当CTRL+C 按下的时候会产生SIGINT信号,trap捕获这个SIGINT信号,并执行 ‘echo -e "\nCTRL_C PRESSED"’这个命令,最终输出echo命令执行的结果, 但是我们同时看到有"^C" 这个符号的输出又是怎么回事呢? 这个属于 对键盘输入中断 的处理结果;如果纯粹的发送 SIGINT 信号,将看不到"^C"这个符号:

代码语言:javascript
复制
[root@www ~]# bash
[root@www ~]# trap 'echo -e "\nCTRL-C Pressed." ' SIGINT
[root@www ~]# ^C            #按下ctrl+c的回显;
CTRL-C Pressed.

[root@www ~]# kill -s SIGINT $$        #直接发送SIGINT信号

CTRL-C Pressed.

[root@www ~]# 
再看如下的一个例子:
代码语言:javascript
复制
[root@www ~]# trap 'echo -e "\nCTRL_C PRESSED"' SIGINT
[root@www ~]# sleep 1000
^C
[root@www ~]# 
在这个例子中,当sleep的时候,按下了CTRL+C, 却没有成功捕获SIGINT 信号,为什么呢?

trap以及sleep运行的时候,各自分别产生了一个child process , 把trap对应的child process 记作A, sleep 对应的child process 记作为B. 而trap只是对其父进程起作用,而对父进程的子进程并不起作用,而B进程(sleep)属于A的父进程的子进程;所以trap命令无法对sleep命令的SIGINT起作用; 而如果把着两条命令放到一个脚本中,则会起作用,因为当运行脚本的时候, 按下ctrl+c触发的SIGINT信号被发送到了bash脚本对应的进程,而trap作为脚本中的一条命令,它本身是脚本的子进程,所以其父进程就是脚本进程;因此trap捕获到了SIGINT信号,此时trap捕获的是 发送给脚本的SIGINT信号,而不是发送给sleep的SIGINT信号;也就是说trap不可能捕获发送给sleep的任何信号;

代码语言:javascript
复制
[root@www ~]# cat test.sh 
#!/bin/bash
trap "echo CTRL_C Pressed."  SIGINT
sleep 100
[root@www ~]# bash -x test.sh
+ trap 'echo CTRL_C Pressed.' SIGINT
+ sleep 100
^C++ echo CTRL_C Pressed.
CTRL_C Pressed.
[root@www ~]# 

C. 从上述介绍的trap可以捕获signal的范围来讲,trap的使用基本都是在 bash服务脚本中:

  1. 接受到特定信号的时候,用于kill 进程;比如: trap "kill $THIS_PID" SIGTERM , 这样保证当脚本收到SIGTERM信号的时候,可以结束特定的服务进程;
  2. 用于清理运行中的临时文件,比如: 如果用户按下了ctrl+c, 或者shell脚本收到了sigterm信号等,这时候可能有临时文件没有被移除,可以通过 trap来清理临时文件;
  3. 对于特定的SIGNAL, 可以返回指定的"exit code', 比如 下面的例子,如果按下ctrl+c, 那么$?的值为5.
代码语言:javascript
复制
#!/bin/bash
trap "exit 5"  SIGINT
sleep 100

D. 关于trap命令的扩展: 1)显示特定SIGNAL的trap action:

代码语言:javascript
复制
[root@www ~]# trap -p SIGINT SIGTERM
trap -- 'echo 123' SIGINT
trap -- 'echo 123' SIGTERM
[root@www ~]# 

2)取消trap action的设置:

代码语言:javascript
复制
[root@www ~]# trap  SIGINT 
[root@www ~]# trap  SIGTERM
[root@www ~]# trap -p SIGINT SIGTERM
[root@www ~]# 

本文原创,转载请著名出处

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 看下面的例子:
  • 再看如下的一个例子:
  • 在这个例子中,当sleep的时候,按下了CTRL+C, 却没有成功捕获SIGINT 信号,为什么呢?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档