Awk

awk 的行為與 tail 與 inotifywait 不同

  • January 31, 2021

awk在分析tail -fvs的輸出時表現不同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 >> 3echo OPEN > 3返回字元串,退出程式碼並終止。

echo $?在整個管道(之前的程式碼||)終止後執行。

inotifywait … | awk … || echo …after awkterminates的情況下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 $? 

引用自:https://unix.stackexchange.com/questions/631986