while 循环的“tail -f | grep error”不起作用

while 循环的“tail -f | grep error”不起作用

以下命令没有给出任何结果。我想grep从文件中提取错误行并将其插入表中。

不起作用的命令:

tail -f logfile.log | grep  ERROR|while read msg; do psql -d testdb -c insert into t values('$msg'); done

但如果我grep ERROR从命令中删除代码,它就会按预期工作。我不知道发生了什么事?

运行良好的命令:

tail -f logfile.log|while read msg; do psql -d testdb -c insert into t values('$msg'); done

您可以假设文件中有以下数据:

ERROR
sql committed
ERROR
ERROR
error
...

答案1

两件事情:

  1. 正如问题中所写的,代码将插入文字字符串$msg(如果它有效的话),因为您在它周围使用了单引号。请改用双引号。在这里,我将整个语句放在双引号中,这将扩展内部$msg。 shell 代码仍然很脆弱,具体取决于grep.理想情况下,应正确清理in 中的字符串,$msg以便单个'或其他特殊字符不会破坏语句(或更糟糕的是,请参阅来自用户的评论CAS以下)。

    tail -f logfile.log |
    grep -F 'ERROR' |
    while read msg; do
        psql -d testdb -c "insert into t values('$msg')"
    done
    

    当我们使用固定字符串进行搜索时,我还添加了-F调用(这主要用于文档目的)。grep

  2. grep缓冲其输出,因此在其输出缓冲区已满之前不会产生任何内容。这给人的印象是它“不起作用”,而实际上它确实起作用,但它不会执行任何操作,直到grep刷新其输出缓冲区,一旦有足够的数据,它就会执行此操作。这是一个性能优化。

    GNU grep(以及同一实用程序的一些其他实现,例如 OpenBSD)可以通过其--line-buffered选项进行行缓冲:

    tail -f logfile.log |
    grep --line-buffered -F 'ERROR' |
    while read msg; do
        psql -d testdb -c "insert into t values('$msg')"
    done
    

注意:我还没有测试过这个,因为我目前没有运行 PostgreSQL (?) 实例。

相关内容