shell脚本专家指南笔记#7_非直接引用变量

本文介绍如何使用Shell脚本来监控日志文件的变化,通过动态变量实现对多个日志文件的独立监控,包括日志追加和滚动的处理,以及发送警告或错误通知。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

##
# 本文为《shell脚本专家指南》一书的学习笔记。
##

7. 非直接变量

直接变量的概念
    明确知道变量的名字,可以不先知道变量的值。
    创建直接变量的三种方式。
        直接赋值。  # a=b
        存储一个命令的输出。  # a=`echo b`
        存储某些类型的计算结果。  # a=$(( 1 + 2 ))

非直接变量的概念
    在程序运行中创建的变量,可能不知道执行过程中需要的变量的具体名字。
    也称动态变量。

通过eval命令,使用动态变量。
    eval 命令,原文给的意思是"评估"。可以这么理解,正常来讲,我们向shell
    提交一条命令,比如 
        var=abc; echo $var 
    那么输出是abc,shell在执行前,会将变量进行替换,就是将 $var 
    替换为了 abc ,实际shell执行的命令是 echo abc 。
    eval的作用,是在将命令传入shell前,先进行了一次变量替换而不执行,
    就是说命令的变量被替换了两次。那么看下面这条命令
        var=abc; v=var; eval echo '$'$v
    输出是 abc,可以理解为,eval echo '$'$v ,首先被eval命令进行变量替换,
    就是 $v 替换为了 var, 那么命令再被传入shell执行前,shell看到
    的命令就是 echo $var 了。
    同样的,定义和提取变量,通过eval命令,就实现了非直接变量的使用。通过动态变量,监控日志文件。
示例-----------------------------------------------------------------
 

#!/bin/bash
# set -x
# 是否开启DEBUG,1开启,0关闭。
DEBUG=1
# 每次扫描日志文件的间隔,单位秒。
DELAY=60
# 示例内容可以排版为
#   /var/log/messages:authentication%20failure:rebpeters:warn \
#   /var/log/messages:recv%20failure::error
# 格式,日志文件名:扫描关键字:排除关键:日志级别
# 其中 %20 最后会用 空格 替换。
# 空格隔开的每个条目,都是需要监控的一个监控点。
# 可以实现对多个日志文件进行独立监控。
LOGCHKS="/var/log/messages:authentication%20failure:\
rebpeters:warn /var/log/messages:recv%20failure::error"

# 主循环,最后用sleep结尾,实现间隔扫描。
while :; do
  # 用于每个主循环中,拼凑动态变量,实现次级循环的变量的隔离。
  entry_count=0
  # 次级循环,对LOGCHKS中的每个条目进行一次扫描。
  for LOGCHK in `echo $LOGCHKS`; do
    logfile=`echo $LOGCHK | cut -d: -f1`
    strings=`echo $LOGCHK | cut -d: -f2`
    strings=`echo $strings | sed -e "s/%20/ /g"`
    exceptions=`echo $LOGCHK | cut -d: -f3`
    exceptions=`echo $exceptions | sed -e "s/%20/ /g"`
    notify=`echo $LOGCHK | cut -d: -f4`
    entry_count=`expr $entry_count + 1`
    suffix=`echo $logfile | sed -e s/\\\//_/g`
    suffix=`echo $suffix | sed -e s/\\\./_/g`

    # 判定是否为脚本首次执行,脚本首次执行时COUNT${suffix}_$entry_count变量为空。
    # 需要对 BASE${suffix}_$entry_count 进行初始化,初始化为当前日志的行数。
    if [ "`eval echo '$COUNT'${suffix}_$entry_count`" = "" ]; then
      eval BASE${suffix}_$entry_count=`wc -l $logfile | awk '{print $1}'`
    fi

    eval COUNT${suffix}_$entry_count=`wc -l $logfile | awk '{print $1}'`

    # 通过对比上次主循环结束时的行数 BASE${suffix}_$entry_count 和 
    # 当前日志行数 COUNT${suffix}_$entry_count 进行对比,判断日志是否追加或滚动。
    #
    # 日志追加,扫描出新增的行数,并用tail命令将新增日志进行处理。
    if [ "`eval echo '$COUNT'${suffix}_$entry_count`" -gt "`eval echo '$BASE'${suffix}_$entry_count`" ]; then
      LINES=`eval expr '$COUNT'${suffix}_$entry_count - '$BASE'${suffix}_$entry_count`
      eval BASE${suffix}_$entry_count='$COUNT'${suffix}_$entry_count
      if [ "$exceptions" != "" ]; then
        MSGS=`tail -$LINES $logfile | egrep -i "$strings" | egrep -iv "$exceptions"`
        test $DEBUG -gt 0 && echo "MSGS is $MSGS"
      else
        MSGS=`tail -$LINES $logfile | egrep -i "$strings"`
        test $DEBUG -gt 0 && echo "MSGS is $MSGS"
      fi
      if [ "$MSGS" ]; then
        if [ "$notify" != "error" ]; then
          echo Send a warning notification.
        else
          echo Send a error notification.
        fi
      fi
    # 日志发生滚动,直接对的当前日志进行全文件扫描。
    elif [ `eval echo '$COUNT'${suffix}_$entry_count` -lt `eval echo '$BASE'${suffix}_$entry_count` ]; then
      eval BASE${suffix}_$entry_count='$COUNT'${suffix}_$entry_count
      if [ "$exceptions" != "" ]; then
        MSGS=`cat $logfile | egrep -i "\"$strings\"" | egrep -iv "$exceptions"`
        test $DEBUG -gt 0 && echo "MSGS is $MSGS"
      else
        MSGS=`cat $logfile | egrep -i "\"$strings\""`
        test $DEBUG -gt 0 && echo "MSGS is $MSGS"
      fi
      if [ ! "$MSGS" ]; then
        if [ "$notify" != "error" ]; then
          echo Send a warning notification.
        else
          echo Send a error notification.
        fi
      fi
    # 日志未变化,不做操作。
    else
      test $DEBUG -gt 0 && echo "No change in size of $logfile."
    fi
  done
  sleep $DELAY
done

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值