tail -f 然後在匹配字串時退出

tail -f 然後在匹配字串時退出

我正在嘗試配置一個啟動腳本,該腳本將啟動 tomcat,監視 catalina.out 中的字串“伺服器啟動”,然後運行另一個進程。我一直在嘗試 tail -f 與 grep 和 awk 的各種組合,但還沒有任何工作。我遇到的主要問題似乎是在 grep 或 awk 匹配字串後強制尾部死亡。

我已簡化為以下測試案例。

test.sh is listed below:

#!/bin/sh    
rm -f child.out
./child.sh > child.out &
tail -f child.out | grep -q B

child.sh is listed below:

#!/bin/sh
echo A
sleep 20
echo B
echo C
sleep 40
echo D

我看到的行為是 grep 在 20 秒後退出,但尾部還需要 40 秒才能消失。我理解為什麼會發生這種情況 - tail 僅在寫入時才會注意到管道消失了,這僅在資料附加到檔案時才會發生。由於 tail 將緩衝資料並將 B 和 C 字元作為單一寫入輸出(我透過 strace 確認了這一點),這一事實使情況變得更加複雜。我嘗試使用在其他地方找到的解決方案來解決這個問題,例如使用 unbuffer 命令,但這沒有幫助。

有人對如何讓它按照我的預期工作有任何想法嗎?或者等待 Tomcat 成功啟動的想法(考慮等待 TCP 連接埠知道它已經啟動,但懷疑這會變得比我現在嘗試做的更複雜)。我已經設法讓它與 awk 一起工作,在比賽中執行“killall tail”,但我對這個解決方案並不滿意。注意我正在嘗試讓它在 RHEL4 上運行。

答案1

像這樣的東西嗎?

mkfifo child.fifo
tail -f child.out > child.fifo &
pid=$!
grep -q B child.fifo && kill $pid

在全:

#!/bin/sh    
rm -f child.out
./child.sh > child.out &
mkfifo child.fifo
tail -f child.out > child.fifo &
pid=$!
grep -q B child.fifo && kill $pid
rm child.fifo

好像20秒就跑完了。

$ time ./test2.sh

real    0m20.156s
user    0m0.033s
sys     0m0.058s

更新

這種方法似乎也有效:

#!/bin/sh
rm -f child.out
./child.sh > child.out &
(tail -f child.out | grep -q B child.out)

如果您有時看到它立即退出,請嘗試新增 sleep 1,即

#!/bin/sh
rm -f child.out
./child.sh > child.out &
sleep 1
(tail -f child.out | grep -q B child.out)

答案2

全部在一行,將 'do foo' 替換為 command'

# 服務tomcat6啟動
#尾-f /var/log/tomcat6/catalina.out | awk '/伺服器啟動/{system("do foo");退出 0}'

答案3

失去尾巴。由於您從空的 child.out 開始,因此您不需要它並且(正如您所發現的)它使事情變得複雜。只需 grep 才能找到睡眠循環中的第一個實例。

until fgrep -q "Server startup" child.out; do sleep 1; done

如果您確實需要保留尾部,因為您並不總是以空的 catalina.out 開頭,請將尾部放在循環內:

until tail child.out| fgrep -q "Server startup"; do sleep 1; done

相關內容