Bash

tail -f 然後在匹配的字元串上退出

  • June 24, 2012

我正在嘗試配置一個啟動腳本,它將啟動 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 seconds 後退出,但是 tail 還需要 40 秒才能死掉。我理解為什麼會發生這種情況 - tail 只會在寫入管道時注意到管道已經消失,這僅在數據附加到文件時才會發生。更複雜的是,tail 將緩衝數據並將 B 和 C 字元作為單次寫入輸出(我通過 strace 確認了這一點)。我試圖用我在其他地方找到的解決方案來解決這個問題,比如使用 unbuffer 命令,但這並沒有幫助。

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

像這樣的東西?

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)

引用自:https://serverfault.com/questions/214691