zoukankan      html  css  js  c++  java
  • bash信号捕捉

    我们ping一个主机,然后按下ctrl+c那么就会终止这个ping动作,如下图:

    可是如果使用一个循环来逐个ping不同主机,你再按下ctrl+c就会发现停不下来,直到循环完成,如下图:

    #!/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命令。

    trap -l显示系统信号[1]kill -l也是可以显示的。

    trap命令不能捕捉SIGKILL和SIGTERM这两个信号。捕捉信号的目的是一旦信号到达我们针对信号做什么处理,如果捕捉SIGKILL并且你修改了行为,这就意味着这个进程刀枪不入了,这显然不行。一般我们捕捉SIGHUP、SIGINT等。

    针对上面的例子如何修改呢?

    #!/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循环是否执行完毕它都随着脚本的退出而终止。

    如果你想让捕捉信号时做更多操作,你可以使用函数的方式,如下代码:

    #!/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
    

    也就是突然终止后需要做一些收尾的清理操作,你就可以通过上面自定义一个函数来执行。


    1. 信号是进程间通信的一种方式 ↩︎

  • 相关阅读:
    Centos7重置Mysql 8.0.1 root 密码
    MysQL使用一高级应用(下)
    MysQL使用一高级应用(上)
    MysQL使用一查询
    MysQL使用一创建库与表
    OSI七层协议模型、TCP/IP四层模型学习笔记
    python-作用域和装饰器
    python-正则表达式RE
    python-高阶函数和闭包
    python-内置函数及捕获异常
  • 原文地址:https://www.cnblogs.com/rexcheny/p/10849763.html
Copyright © 2011-2022 走看看