美文网首页
使用 bash 进行服务闲置检查

使用 bash 进行服务闲置检查

作者: 虚胖一场 | 来源:发表于2019-08-10 20:24 被阅读0次

    本文链接个人站 | 简书 | CSDN
    版权声明:除特别声明外,本博客文章均采用 BY-NC-SA 许可协议。转载请注明出处。

    重启服务之前往往需要检查一下是否还有未处理完的请求。此时可以使用 ss 命令查看端口是否还有 TCP 连接。例如:

    pi@raspberrypi:~ $ ss -nt state established src 192.168.1.26:8888
    Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    0      0      192.168.1.26:8888               192.168.1.25:50390
    

    我们可以统计这条命令输出的行数,若小于 2,则说明服务已经处于闲置状态。脚本如下:

    #!/bin/bash
    
    # 获取本机 IP
    host=$(ifconfig -a | grep inet | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | tr -d "addr:")
    # 超时时间
    timeout=3600
    
    check(){
      port="$1"
      begin=$(date +'%s')
      while true
      do
        current=$(date +'%s')
        duration=$(($current-$begin))
        if [[ $duration -gt $timeout ]]; then
          # 超时退出
          result="TIMEOUT"
          code=1
          break
        count=$(ss -nt state established src $host:$port | wc -l)
        if [[ $count -lt 2 ]]; then
          # 闲置退出
          result="IDLE"
          code=0
          break
        else
          sleep 2
        fi
      done
      echo "the result is $result"
      return $code
    }
    
    if [[ $# -ne 1 ]]; then
      echo "Usage: $0 [port]"
      exit 1
    else
      check "$1"
      exit $?
    fi
    

    如果 ss 命令发生错误怎么办?为了进一步完善脚本,我们需要加入异常处理机制。bash 中没有 try...catch.. 之类的语法,那么该如何捕获异常呢?下面介绍两个特殊的写法:

    • command1 || command2:当且仅当 command1 发生错误时执行 command2
    • command1 && command2:当且仅当 command1 没有错误时执行 command2

    利用上面这两个特性,我们引入异常处理,把脚本改写成:

    #!/bin/bash
    
    set -o pipefail
    
    # 获取本机 IP
    host=$(ifconfig -a | grep inet | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | tr -d "addr:")
    # 超时时间
    timeout=3600
    
    check(){
      port="$1"
      begin=$(date +'%s')
      while true
      do
        current=$(date +'%s')
        duration=$(($current-$begin))
        if [[ $duration -gt $timeout ]]; then
          # 超时退出
          result="TIMEOUT"
          code=1
          break
        {
          count=$(ss -nt state established src $host:$port | wc -l) &&
          if [[ $count -lt 2 ]]; then
            # 闲置退出
            result="IDLE"
            code=0
            break
          else
            sleep 2
          fi
        }||{
          # 异常退出
          result="ERROR"
          code=1
          break
        }
      done
      echo "the result is $result"
      return $code
    }
    
    if [[ $# -ne 1 ]]; then
      echo "Usage: $0 [port]"
      exit 1
    else
      check "$1"
      exit $?
    fi
    

    ss -nt state established src $host:$port | wc -l 利用了管道,而默认情况下,前面的 ss 命令出错并不会影响后面的 wc 命令的执行。为了捕获管道中的错误,我们在脚本开头添加了 set -o pipefail

    现在我们的脚本可以检测一个服务实例是否闲置。如果我们需要同时检查多个实例该怎么办?如果可以并行地执行我们的 check 函数就好了。我们知道,在一条命令后面加上 &,就可以将它放到子 shell 中执行,达到多线程的效果。进一步地,我们可以用 wait 命令实现多线程同步。基于此,我们给出可以同时检查多个实例的 check_all 函数:

    check_all(){
      ports="$#"
      anyfailed=0
      for port in $ports
      do
        check $port &
      done
      for pid in $(jobs -p)
      do
        wait $pid
        if [[ $? -ne 0 ]]; then
          anyfailed=1
        fi
      done
      return $anyfailed
    }

    相关文章

      网友评论

          本文标题:使用 bash 进行服务闲置检查

          本文链接:https://www.haomeiwen.com/subject/xxqdjctx.html