2018-9-17-bash之信号捕捉
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018-9-17-bash之信号捕捉相关的知识,希望对你有一定的参考价值。
一、概述
我们在上一章当中示例了检测ip地址是否在线的脚本,但是有一个问题,运行的过程中,无论使用Ctrl+c
怎么制止,并没有什么卵用,还是继续运行,直到将最后一个IP地址ping
完,无法制止,只是将当前的ping操作结束,下一个ping
操作就要运行,但是如果连续的按下快捷键,总有一个信号捕捉到,但只有被当前进程的脚本捕捉到才能够停止,而不是ping进程,这就是信号。
我们也可以手动定制信号捕捉的功能,那么如何自定义信号捕捉的处理,那么在ping
操作时,由于信号捕捉不到,那么能不能在捕捉信号之后做出相应的处理操作,对于bash
而言这是可以的,在系统当中有一个trap
命令,通过部署一个陷阱捕捉到信号,或者激发其某个事件进行捕捉处理。
我们可使用-l
选项来列出可捕捉的所有信号。
# 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
不过,使用kill -l
也是获得相同的结果,不过要想了解其信号意义,我们可通过man
手册来进行查看。
信号捕捉:
列出信号:
trap -l
kill -l
man 7 signal
信号是进程间通信间的一种机制,而trap
命令可以让bash
脚本自定义如何捕捉信号,但需要注意的是,不能捕捉TERM
和KILL
的信号,因为捕捉信号的意义在于一旦捕捉到之后能够作出什么操作,因此一般捕捉到信号为HUP
以及INT
等,当然其它的信号也可以捕捉,但是没有以上这两个用的那么频繁。
常用的信号:
HUP, INT
示例:
#!/bin/bash
trap ‘echo "Dou ni wan"‘ INT
for i in {1..254}; do
if ping -W1 -c1 192.168.$i.1 &> /dev/null; then
echo "192.168.$i.1 is up."
else
echo "192.168.$i.1 is down."
fi
done
# bash trap.sh
192.168.1.1 is down.
192.168.2.1 is down.
^CDou ni wan
192.168.3.1 is down.
^CDou ni wan
192.168.4.1 is down.
^CDou ni wan
192.168.5.1 is down.
^CDou ni wan
192.168.6.1 is down.
从以上的运行结果看出,一旦发出Ctrl+c
就是INT
信号后,会显示出Dou ni wan
,但是其实并没有停止其ping
进程,只是停止了当前的ping
,而下一个循环的ping
开始运行,如果彻底退出的当前bash进程的话,要用另一种方式。
#!/bin/bash
trap ‘echo "quit"; exit 1‘ INT
for i in {1..254}; do
if ping -W1 -c1 192.168.$i.1 &> /dev/null; then
echo "192.168.$i.1 is up."
else
echo "192.168.$i.1 is down."
fi
done
那么这就是trap命令的意义,能够其捕捉信号,且捕捉到信号后,使用所定义好的命令来进行处理如何进行,那么以上的信号处理就是显示quit并退出shell进程。
那么trap命令的方法很简单,后面跟上其参数,并跟上信号声明,而一旦捕捉到其信号之后,我们作出什么样的处理操作,而它的命令用法为:
trap ‘COMMAND‘ SIGNALS
我们可以使用以函数中所定义好的命令的形式来对trap
进行定义而后对其进行捕捉。
#!/bin/bash
#
trap ‘mytrap‘ INT
mytrap() {
echo "Quit"
exit 1
}
for i in {1..254}; do
if ping -W1 -c1 192.168.$i.1 &> /dev/null; then
echo "192.168.$i.1 is up"
else
echo "192.168.$i.1 is down"
fi
done
而在每次ping
操作完成之后,可创建其临时文件保存其相关的信息。放在循环内部,每一次创建完成可保证将其可以删除,也需要保证三叉输出。
但是这样的话会创建无数个临时文件,我们需要创建其数组用来其追加到最后一个元素中,遇到终止信号时将其文件进行删除。
#!/bin/bash
#
declare -a hosttmpfiles
trap ‘mytrap‘ INT
mytrap() {
echo "Quit"
rm -f ${hosttmpfiles[@]}
exit 1
}
for i in {1..254}; do
tmpfile=$(mktemp /tmp/ping.XXXXXX)
if ping -W1 -c1 192.168.$i.1 &> /dev/null; then
echo "192.168.$i.1 is up" | tee $tmpfiles
else
echo "192.168.$i.1 is down" | tee $tmpfiles
fi
hosttmpfiles[${#hosttmpfiles[*]}]=$tmpfile
done
echo ${hosttmpfiles[@]}
在信号捕捉中的函数内部可以写出一些复杂的处理逻辑,包括退出及删除未处理的文件等。
二、在bash中使用ASCII颜色
在echo
命令中如何进行着色是一件很简单的事情,关于相关的教程网上也是一抓一大把,那么其着色定义格式为: