awk 的行為與 tail 與 inotifywait 不同
awk
在分析tail -f
vs的輸出時表現不同inotifywait -m
。具體來說,我正在搜尋匹配的字元串,並希望在awk
它出現後退出。這適用於tail -f
,但是在 的情況下inofitywait
,awk
需要觸發兩次。為什麼這樣?可重現的例子:
假設我們在任何一種情況下都在搜尋特定的字元串(“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
返回字元串,退出程式碼並終止。
echo $?
在整個管道(之前的程式碼||
)終止後執行。在
inotifywait … | awk … || echo …
afterawk
terminates的情況下inotifywait
仍然執行。SIGPIPE
只有當(何時)它試圖寫更多時,它才會得到。再次嘗試touch test.file
到達這一點並觸發echo
。另一方面
tail
,在退出tail -f … | awk …
後立即終止,awk
因為GNUtail
採取了特殊步驟來檢測這種情況。為了使用 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 $?