【问题标题】:Shell function to tail a log file for a specific string for a specific time用于在特定时间跟踪特定字符串的日志文件的 Shell 函数
【发布时间】:2012-12-21 02:39:58
【问题描述】:

我需要做以下事情来确保我的应用服务器是

  1. 跟踪特定字符串的日志文件
  2. 在打印该字符串之前保持阻塞
  3. 但是,如果字符串在大约 20 分钟内未打印,则退出并抛出异常消息,例如“服务器需要超过 20 分钟才能启动”
  4. 如果日志文件中打印了字符串,则退出循环并继续。

有没有办法在 while 循环中包含超时?

【问题讨论】:

    标签: linux grep tail


    【解决方案1】:
    #!/bin/bash
    tail -f logfile | grep 'certain_word' | read -t 1200 dummy_var
    [ $? -eq 0 ]  && echo 'ok'  || echo 'server not up'
    

    这会读取写入日志文件的任何内容,搜索 certain_word,如果一切正常,则回显 ok,否则在等待 1200 秒(20 分钟)后它会抱怨。

    【讨论】:

    • Jim,你能解释一下 'read -t 1200 dummy_var' 在这里做什么吗?
    • @Kevin read -t 适用于更高版本的 bash。这在我的 4.1.0 版本上运行良好。如果您尝试从 bash 命令行“帮助读取”,它将提供您的 bash 版本支持的选项。
    • 我做了“帮助阅读”,它确实支持超时选项 -t 超时超时,如果在 TIMEOUT 秒内没有读取完整的输入行,则返回失败。 TMOUT 变量的值是默认超时。 TIMEOUT 可能是一个小数。如果 TIMEOUT 为 0,则仅当指定文件描述符上的输入可用时,读取才会返回成功。如果超时,退出状态大于 128。我的 bash 版本也是 4.2.24(1)-release (x86_64-pc-linux-gnu)
    • 那我不知道为什么调试器有问题。你调试得怎么样了?
    • 阅读永远不会返回给我。在 OSX 和 Linux 下尝试过,Bash 版本分别为 3.2.48 和 3.2.25。
    【解决方案2】:

    你可以这样做:

    start_time=$(date +"%s")
    while true
    do
        elapsed_time=$(($(date +"%s") - $start_time))
        if [[ "$elapsed_time" -gt 1200 ]]; then
            break
        fi
        sleep 1
        if [[ $(grep -c "specific string" /path/to/log/file.log) -ge 1 ]]; then
            break
        fi
    done
    

    【讨论】:

    • 如果日志文件很大或快速增长,则会严重滥用磁盘。
    • 加上计算时间滥用,因为你一次又一次地 grep。您至少可以将grep -F 用于固定字符串。
    【解决方案3】:

    您可以使用 shell 脚本中的信号处理程序(请参阅 http://www.ibm.com/developerworks/aix/library/au-usingtraps/index.html)。

    基本上,您会定义一个要在信号 17 上调用的函数,然后在后台放置一个子脚本,以便稍后发送该信号:

    timeout(pid) {
       sleep 1200
       kill -SIGUSR1 $pid
    }
    
    watch_for_input() {
       tail -f file | grep item
    }
    
    trap 'echo "Not found"; exit' SIGUSR1
    timeout($$) &
    watch_for_input
    

    然后,如果您达到 1200 秒,您的函数将被调用,您可以选择要执行的操作(例如向正在监视您的模式的 tail/grep 组合发出信号以杀死它)

    【讨论】:

    • 我正在为下面的 read -t 投票...我需要更多的麻烦来完成这么简单的任务...
    【解决方案4】:
    time=0
    found=0
    while [ $time -lt 1200 ]; do
      out=$(tail logfile)
      if [[ $out =~ specificString ]]; then
        found=1
        break;
      fi  
      let time++
      sleep 1
    done
    echo $found
    

    【讨论】:

    • 如果文件快速增长,这将不起作用...你会错过行
    • 这可能会引入滑动窗口问题,因为sleep 1以外的指令也会占用执行时间。
    • 我不认为我们在这里处理实时准确性。是的,如果记录器输出很快,这可能会丢失,但这可以根据要求进行修复。
    【解决方案5】:

    接受的答案不起作用并且永远不会退出(因为尽管read -t 退出,先前的管道命令(tail -f | grep)只会在尝试写入输出时收到read -t 退出的通知,这永远不会直到字符串匹配为止)。

    单线可能是可行的,但这里有脚本(工作)方法。 每一个的逻辑都是一样的,他们使用kill在超时后终止当前脚本。 Perl 可能比gawk/read -t 更广泛使用

    #!/bin/bash
    
    FILE="$1"
    MATCH="$2"
    
    # Uses read -t, kill after timeout
    #tail -f "$FILE" | grep "$MATCH" | (read -t 1 a ; kill $$)
    
    # Uses gawk read timeout ability (not available in awk)
    #tail -f "$FILE" | grep "$MATCH" | gawk "BEGIN {PROCINFO[\"/dev/stdin\", \"READ_TIMEOUT\"] = 1000;getline < \"/dev/stdin\"; system(\"kill $$\")}"
    
    # Uses perl & alarm signal
    #tail -f "$FILE" | grep "$MATCH" | perl -e "\$SIG{ALRM} = sub { `kill $$`;exit; };alarm(1);<>;"
    

    【讨论】:

      猜你喜欢
      • 2015-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-20
      • 2020-10-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多