Bash While循环,读取日志文件并在字符串;“关闭完成”;存在

Bash While循环,读取日志文件并在字符串;“关闭完成”;存在,bash,Bash,我正在为我的公司编写一个bash脚本,当服务器被修补时,它会关闭服务器上的相关服务 我试图在脚本中创建一个while循环,它跟踪jboss日志文件,并在出现“shutdown complete”时完成 我的想法是如何做到这一点: while [$SHUTDOWNSTATUS = ]; do tail -f serverlog | grep 'Shutdown complete' SHUTDOWNSTATUS='Shutdown complete' done; 我想这不是最初的

我正在为我的公司编写一个bash脚本,当服务器被修补时,它会关闭服务器上的相关服务

我试图在脚本中创建一个while循环,它跟踪jboss日志文件,并在出现“shutdown complete”时完成

我的想法是如何做到这一点:

  while [$SHUTDOWNSTATUS = ]; do
  tail -f serverlog | grep 'Shutdown complete'
  SHUTDOWNSTATUS='Shutdown complete'
   done;
我想这不是最初的想法。这就是我在陷入困境之前所做的。循环永远不会完成,因为尾部永远不会停止


我正在研究“读取”命令。这能更好地满足我的需要吗?

我觉得应该有比这更好的主意,但我不能马上想到一个

只需循环(使用睡眠延迟),直到文件上的
grep
返回true。(不幸的是,这意味着每次循环都要重新读取整个文件,但避免这样做更为复杂。)


一种方法是将日志文件重定向到文件描述符,然后读取文件描述符,直到日志文件中出现“关机完成”。然后终止循环。例如:

#!/bin/bash

lfn=${1:-dat/jboss.log}     # logfile (default: dat/jboss.log for test)

## test log is readable
[ -r "$lfn" ] || {
    printf "error: file '%s' is not readable.\n" "$lfn"
    exit 1
}

## redirect log to fd 3 and read until "Shutdown complete"
while :; do

    read -r -u 3 line
    if [[ $line =~ "Shutdown complete" ]]; then
        sdstatus=complete
        break
    else
        sleep 5 # adjust sleep as needed
    fi

done 3< "$lfn"  # temporary redirection of $lfn to 3

printf "Shutdown %s\n" $sdstatus

exit 0

注意:这是一个Bash解决方案,因为使用了子字符串比较运算符
=~

避免重读日志文件的一种方法(或至少尽可能快地重读)是记住上次循环迭代中的文件大小,并跳过那么多字节:

while :; do
    size=$(stat -c "%s" serverlog)
    new_text=$(dd if=serverlog bs="$old_size" skip=1 2>/dev/null)
    if [[ -n $new_text ]]; then
        echo "${new_text%%Shutdown complete*}
        [[ $new_text == *"Shutdown complete"* ]] && break
        old_size=$size
    fi
    sleep 0.5s
done

您需要在
[
$SHUTDOWNSTATUS
之间留出一个空格,并在
=
的右侧放置一些东西(即使只是一个空字符串
'
)。虽然这不是最优雅的解决方案,但它是我最终实现的。我写这个脚本的很大一部分,也是理解它在做什么。其他答案对我来说没有意义。它们给了我一些需要研究的东西,但我想实现我个人理解的东西。
$ echo "line 1" > dat/jboss.log

$ cat dat/jboss.log
line 1

$ bash shutdown.sh &
[1] 17446

$ echo "patch applied, Shutdown complete" >> dat/jboss.log
$ Shutdown complete

[1]+  Done                    bash shutdown.sh

$ cat dat/jboss.log
line 1
patch applied, Shutdown complete
while :; do
    size=$(stat -c "%s" serverlog)
    new_text=$(dd if=serverlog bs="$old_size" skip=1 2>/dev/null)
    if [[ -n $new_text ]]; then
        echo "${new_text%%Shutdown complete*}
        [[ $new_text == *"Shutdown complete"* ]] && break
        old_size=$size
    fi
    sleep 0.5s
done