目标:我想对下面代码中显示的tail
命令中的每一行传入数据进行实时模式匹配。
问题:尽管tail
命令和while-loop
在起作用,但是随着数据线的进入,似乎没有某种模式匹配。
#!/bin/bash
#
# Description:
#
# Usage:
#
function interval ()
{
echo $(date '+%y%m%d %H%M%S') $cnt
cnt=0
}
declare -i cnt=0
trap interval SIGUSR1
target_file=${1:-access.log)
shopt -s lastpipe
tail -f --pid=$$ ${1:-access.log} | grep --line-buffered "20" | while read aline
do
let cnt++
done < <( grep --line-buffered "20" )
您的问题在这里:
tail -f --pid=$$ ${1:-access.log} | grep --line-buffered "20" | while read aline
do
let cnt++
done < <( grep --line-buffered "20" )
问题:尽管tail命令和while循环正在运行,但随着数据线的进入,似乎没有任何模式匹配。
你怎么知道?很多时候,使用bash找出问题所在的最简单方法就是拆开各个部分,看看会发生什么。例如。如果您只运行
tail -f --pid=$$ ${1:-access.log} | grep --line-buffered "20"
您将能够看到传递到while循环中的内容。 while循环中的管道会将上述命令的输出发送到while循环中。这就是它的输入。将输入发送到while循环中的另一种方法是您在此处执行的进程替换:
done < <( grep --line-buffered "20" )
您进入while循环的管道正在提供输入。这行也是。您应该只使用这些方法之一。但是,此行不执行任何操作,因为它本身需要输入。如果您自己运行该命令,则会看到终端挂起,等待您的输入。尝试自己在终端上运行以下命令:
grep --line-buffered "20"
什么都不会发生。因此,您使用2种方法将输入发送到while循环中,并且只应使用一种方法:
tail -f --pid=$$ ${1:-access.log} | grep --line-buffered "20" | while read aline
do
let cnt++
done
或...
while read aline
do
let cnt++
done < <( tail -f --pid=$$ ${1:-access.log} | grep --line-buffered "20" )
当然,有一种更简单的方法可以完成所有这些操作。似乎您正在尝试将cnt变量设置为输出中的行数。而不是使用循环,请尝试使用grep的-c选项为您<< c >>包围线。将整个内容包装在命令替换中,以将其设置为cnt变量:cnt=$(tail -f --pid=$$ ${1:-access.log} | grep -c --line-buffered "20")