Linux 在bash脚本中对带有grep的日志文件使用tail-f

Linux 在bash脚本中对带有grep的日志文件使用tail-f,linux,bash,grep,tail,Linux,Bash,Grep,Tail,我想创建一个脚本,在正在写入的日志文件中对特定字符串进行greps。我想得到第一个结果,并将其放入一个变量中供以后使用。这将通过SSH连接使用,如下所示: ssh 'user@xxx.xxx.xxx.xxx' 'bash -s' < /usr/local/bin/checklog.sh string 当我尝试上面的方法时,没有输出而不是裸 Read ,以避免剥离反斜杠文字,而使用卷轴却没有好处,当他们不主动地消除变量名时,在它们所处的位置,您就丢失了引号。(当然,对于没有空格或全局字符的

我想创建一个脚本,在正在写入的日志文件中对特定字符串进行greps。我想得到第一个结果,并将其放入一个变量中供以后使用。这将通过SSH连接使用,如下所示:

ssh 'user@xxx.xxx.xxx.xxx' 'bash -s' < /usr/local/bin/checklog.sh string

当我尝试上面的方法时,没有输出

不做您认为它做的事。
它将前面命令的输出重定向到名为
$var
的文件。
要捕获命令的输出并将其放入变量中,请使用
variableName=“$(…)”


谢谢大家的意见。您帮助找到了更好的方法,使用while和tail而不使用-f

werd=$1
var=""
while [ "${var}" == "" ]
do
var=$(tail -1 /var/log/named.log | grep "${werd}");
done
echo "${var}";

这只是读取文件中的最后一行。由于文件正在写入,所以最后一行发生了变化,这就是我要查找的结果

使用
while
循环可能适合您的情况,但请注意,它不能保证捕获日志文件的每一行。考虑日志写入器包含一个写两行的动作:
Something bad just happened:\nError xyz on line 22
当循环执行
tail-1
操作时,它很可能只看到第二行

不仅如此,while循环实现还意味着您在一个循环中旋转CPU,不断地发出
tail
命令(看看
top
,而
while
实现运行,而不是
tail-f

如果您只想在模式匹配后停止监视,则有一些很好的建议。(注意尾部流程的问题。)

这个怪物可能不是最优的,但它捕获每一行,在等待新行时使用最少的CPU,完成后终止尾部,并使您能够灵活地编写一些额外的逻辑(例如根据不同的匹配模式执行操作):

watchPattern=$1
logFile=/var/log/named.log
logLine=“”
而read-r对数线;做
#我们有火柴吗?
如果[[“$logLine”=*“$watchPattern”*];然后
#确认消息,写入控制台(例如,不需要)
echo“找到了匹配项。”
#扼杀尾部进程(一次假定一个进程的一点技巧)
kill$(ps-eopid,命令| awk-v pattern=“tail-fn0$logFile”'$0~pattern&&!/awk/{print$1}')
#离开这里
打破
fi

完成<我如何将其放入脚本中?我尝试过这样做,但它不会回显输出
tail-f文件| grep…
永远不会退出,因此您的
echo
语句永远不会执行。
tail-f
如果文件离开,但缺少它永远运行的那种东西,它将退出。这是有意义的。当我取出
>$var
时,我想它至少会打印出结果。这并不意味着问题在于,当我正在为该字符串进行grepping时,文件正在被写入。我是否可以添加一些逻辑使其退出,或者我需要考虑另一种方法?
$var
的意思是“将stdout重定向到文件$var”,那么您期望什么呢?仅供参考,
==
在POSIX
测试中无效(aka
[
);唯一标准的保证字符串比较运算符是
=
。顺便说一句,这在性能方面非常昂贵;我不能向其他人推荐它,即使有竞争条件(如果它们被附加得足够快,它可能会丢失行。我可能会考虑<代码> Real-Re/COD>而不是裸<代码> Read <代码>,以避免剥离反斜杠文字,而使用卷轴却没有好处,当他们不主动地消除变量名时,在它们所处的位置,您就丢失了引号。(当然,对于没有空格或全局字符的日志文件名,它们只会影响IFS的怪异值,但对于
IFS=/
或其他代码留下的东西,这并非闻所未闻)。
“$logfile”
应该用来避免字符串拆分/全局扩展。另外,当我戴着我的学究帽时,
echo“${logLine}”<代码> >只包含<代码> -e < /代码>(用GNU而不是POSIX <代码>回音< /代码>)或<代码> -n>代码>。此外,XSI扩展POSIX ECHO将在这里默认扩展反斜杠转义序列,您可能不需要。请考虑<代码> PrtTf '%s\n '“$LogLIN”。
取而代之的是——请参阅的应用程序用法和基本原理部分,以获得有趣的阅读。也就是说,我只是一个有这个答案的书呆子,因为这是一个非常好的答案。:)…事实上,还有一件事--你可能会考虑完全抛弃子shell。与其在阅读
时插入
并将其放入捕获,你只需在阅读logLine时运行
;do…;done<学究式应用。谢谢你的建议,@charles duffy。
werd=$1
var=""
while [ "${var}" == "" ]
do
var=$(tail -1 /var/log/named.log | grep "${werd}");
done
echo "${var}";
Something bad just happened:\nError xyz on line 22
watchPattern=$1
logFile=/var/log/named.log
logLine=""

while read -r logLine ; do
    #Do we have a match?
    if [[ "$logLine" == *"$watchPattern"* ]] ; then
        #Confirmation message, written to console (for example, not needed)
        echo "Found a match."
        #Kill off the tail process  (a bit of a hack that assumes one at a time)
        kill $(ps -eo pid,command | awk -v pattern="tail -fn0 $logFile" '$0 ~ pattern && !/awk/ {print $1}')
        #Get out of here
        break
    fi
done< <(exec tail -fn0 "$logFile")

#logLine will be the matched value
echo "match = $logLine"