咱们ping一个主机,而后按下ctrl+c
那么就会终止这个ping动做,以下图:shell
但是若是使用一个循环来逐个ping不一样主机,你再按下ctrl+c
就会发现停不下来,直到循环完成,以下图:bash
#!/bin/bash NETWORK=172.16.42. # -W 表示超时时长 -c 是发送几个ping包 for IP in {1..20}; do ping -W 1 -c 10 ${NETWORK}${IP} done
脚本没有中止而是依然继续执行,可是你发现172.16.42.1是通的,并且咱们经过-c参数应该是ping 10次,当完成第5次ping的时候,咱们按下ctrl+c
它就再也不ping这个地址,而是开始ping 172.16.42.2这个地址。这就是ctrl+c
的真正含义,它的做用是终止当前正在执行的操做,脚本中循环20次,每次执行一个ping操做,因此ctrl+c
仅仅终止的是其中一个ping操做而不是整个脚本。函数
不过这么解释并不彻底正确,由于你要知道ctrl+c
是发送中断信号,究竟是应该终止ping操做仍是这个脚本,取决于捕捉到这个中断信号的程序,若是是ping捕捉到了,那么就终止ping操做;若是是执行这个脚本的进程捕捉到就终止这个脚本的执行。那么咱们如何设置捕捉一个信号呢?就使用trap
这个内置的shell命令。ui
trap -l
显示系统信号1,kill -l
也是能够显示的。3d
trap命令不能捕捉SIGKILL和SIGTERM这两个信号。捕捉信号的目的是一旦信号到达咱们针对信号作什么处理,若是捕捉SIGKILL而且你修改了行为,这就意味着这个进程刀枪不入了,这显然不行。通常咱们捕捉SIGHUP、SIGINT等。code
针对上面的例子如何修改呢?blog
#!/bin/bash # 捕捉INT,而后执行exit 1,该命令一般写在脚本第一行 trap 'exit 1' INT NETWORK=172.16.42. # -W 表示超时时长 -c 是发送几个ping包 for IP in {1..20}; do ping -W 1 -c 10 ${NETWORK}${IP} done
再次运行这个脚本那么依然会执行循环,可是trap并不执行而是一直等着信号发生,咱们使用的ctrl+c
其实就是SIGINT信号。这个脚本的含义就是shell捕捉信号,因此shell捕捉到之后就会执行响应动做,咱们这里是trap 'exit 1' INT
捕捉SIGINT而后执行exit 1
,当shell执行这个命令时也就意味着退出了,因此不管for循环是否执行完毕它都随着脚本的退出而终止。进程
若是你想让捕捉信号时作更多操做,你可使用函数的方式,以下代码:it
#!/bin/bash trap 'sig_handler' INT sig_handler(){ echo "Quit" exit 1 } NETWORK=172.16.42. # -W 表示超时时长 -c 是发送几个ping包 for IP in {1..20}; do ping -W 1 -c 10 ${NETWORK}${IP} done
也就是忽然终止后须要作一些收尾的清理操做,你就能够经过上面自定义一个函数来执行。io
信号是进程间通讯的一种方式↩