awk 的 tail 与 inotifywait 的行为不同

awk 的 tail 与 inotifywait 的行为不同

awktail -f分析vs的输出时表现不同inotifywait -m。具体来说,我正在搜索匹配的字符串,并希望awk在它出现后退出。这对于 来说效果很好tail -f,但是在 的情况下inofitywaitawk需要触发两次。为什么这样?


可重复的例子:

假设我们在任何一种情况下都搜索特定的字符串(“OPEN”),并使用特殊的退出代码作为标记。让我们在短暂等待(inotofywait需要一点时间)后触发它并返回退出代码。伪代码:

 command | awk-analysis || get-non-0-exit-code & trigger

一切都好于tail -f

以下 a) 打印该行,b) 返回退出代码,c) 终止。正如预期的那样。

tail -f test.file | awk '/OPEN/ { print $0 ; exit 100 }' || echo $? &
  { sleep 2 ; echo OPEN > test.file ; }

然而与inotifywait -m

结果却截然不同。

inotifywait -m -e OPEN | awk '/OPEN/ { print $0 ; exit 100 }' || echo $? &
  { sleep 2 ; touch test.file ; }

这将打印该行(因此inotifywait被触发并awk看到它),但不显示退出代码也不终止。只有像这样的另一个触发器touch test.file才能停止awk

也许控制字符?

我想也许我在这里缺少一个信号awk用途,所以我尝试使用cat -A(父文件夹中的结果文件,所以否则会触发第二个“OPEN” inotifywait)进行分析:

tail -f test.file | tee >(cat -A >../stream) | ....
cat ../stream
OPEN$

inotifywait -m -e OPEN | tee >(cat -A >../stream) | ....
cat ../stream
./ OPEN test.file$

所以没有遗漏任何看不见的控制字符。

这种行为的原因是什么?

我错过了换行符吗?为什么awk打印该行,但不在exit同一代码块中运行该命令?但为什么它可以与 一起使用tail呢?


版本

awk --verison:GNU Awk 4.2.1,API:2.0(GNU MPFR 4.0.2,GNU MP 6.1.2)

inotifywait -h: inotifywait 3.14

tail --verison:尾部(GNU coreutils)8.30


根据 Kusalananda 的评论进行编辑:

尾部-f

test.file存在并具有以下内容:

*情况1

OPEN
spam

*案例2

spam
OPEN

*情况3(文件为空)

上面的触发器没有运行,即

tail -f test.file | awk '/OPEN/ {print $0 ; exit 100 }' || echo $?

情况 1 & 2 :立即返回匹配行、退出代码并终止。

情况 3:等待,打开其他终端和echo OPEN >> 3/或echo OPEN > 3返回字符串、退出代码并终止。

答案1

echo $?在整个管道(之前的代码||)终止后运行。

在终止inotifywait … | awk … || echo …后仍然运行的情况下。只有当它尝试写更多时它才会得到。再次尝试到达此点并触发。awkinotifywaitSIGPIPEtouch test.fileecho

另一方面,退出后立即终止tail,因为tail -f … | awk …awkGNUtail采取特殊措施来检测这种情况


为了使用 inotifywait 重现这一点,需要转发 PID 并通过 awk 发送 SIGPIPE:

{ inotifywait  -m -e OPEN ./  & echo $! ; } |
awk 'NR==1 {pid=$0}
     /OPEN/ {print $0,pid
             system("echo kill -13 "pid)
             exit 122  }' ||
echo $? 

相关内容