
我正在嘗試配置一個啟動腳本,該腳本將啟動 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