2011-08-24 94 views
7

我想實現一個等待日誌文件中特定消息的腳本。一旦消息被記錄,然後我想繼續該腳本。'grep -q'不能以'tail -f'退出

這裏就是我想出來用tail -fgrep -q

# tail -f logfile | grep -q 'Message to continue' 

grep從沒有放棄過,所以它永遠等待,即使「消息繼續」的文件中被記錄下來。

當我運行這個沒有-f它似乎工作正常。

+0

它可能以緩衝在尾部發生有關。當我運行你的命令時,它不會退出,但在再次寫入文件後退出。 – Kevin

回答

9

tail -f將讀取文件並顯示後面添加的行,它不會終止(除非發送像SIGTERM這樣的信號)。 grep這裏不是阻塞部分,tail -f是。 grep將從管道讀取,直到它關閉,但它不會因爲tail -f不會退出並保持管道打開。


一個解決問題的方法可能會被(未測試,並很可能表現不佳):

tail -f logfile | while read line; do 
    echo $line | grep -q 'find me to quit' && break; 
done 
+0

作爲一個細節,中斷,退出和其他信號也會停止'tail -f'。不過,你的診斷基本上是正確的。 –

+0

@Jonathan:但是在閱讀grep的manpage後我感到困惑。 '-q'應該在第一次匹配後立即退出,所以op **的例子應該可以工作。 grep退出並停止從管道讀取 – knittl

+0

是的,我也是...我對此感到困惑。這對我來說是一種'新'的行爲;我記得'-q'等同於'-s',提前終止是令人驚訝的。我最好的猜測是'grep'通過繼續閱讀避免發送SIGPIPE到'tail',但我沒有證明這一點。 (我要編輯我的評論以刪除第二句,但我沒有及時趕到那裏)。 –

0

這是因爲tail-f(後續)選擇不退出,並繼續將輸出提供給grep。使用perl/python可能會更容易等待日誌文件中的行。

使用Python子流程模塊啓動tail -f。從循環中讀取tail的輸出,直到看到所需的行,然後退出Python腳本。把這個解決方案放在你的shell腳本中。

Python腳本將阻止shell腳本,直到看到所需的行。

0

我想我會張貼此作爲一個答案,因爲它解釋了爲什麼該命令將退出第二寫入到文件後:

touch xxx 
tail -f xxx | grep -q 'Stop' 
ps -ef |grep 'grep -q' 
# the grep process is there 
echo "Stop" >> xxx 
ps -ef|grep 'grep -q' 
# the grep process actually DID exit 
printf "\n" >> xxx 
# the tail process exits, probably because it receives a signal when it 
# tries to write to a closed pipe 
+1

事實上,'tail -f'在試圖向管道寫入新輸出時會發送一個'SIGPIPE',此時管道上的讀取器已經退出。 'tail -f'的問題是_usually_文件的「尾部」將適合對管道的單個寫入,即使讀取器只讀取第一個字節並退出,'SIGPIPE'也不會被髮送,直到隨後的寫入嘗試。 –

3

一些實驗後,我相信這個問題是在bash方式以某種形式或形式等待管道中的所有進程退出。

隨着C源(各種程序級聯幾次以上),部分360行普通文件「QQQ」和使用「grep的-q返回」,那麼我觀察:

  1. tail -n 300 qqq | grep -q return確實幾乎立即退出。
  2. tail -n 300 -f qqq | grep -q return不退出。
  3. tail -n 300 -f qqq | strace -o grep.strace -q return直到中斷纔會退出。該grep.strace文件結尾:

    read(0, "#else\n#define _XOPEN_SOURCE 500\n"..., 32768) = 10152 
    close(1)        = 0 
    exit_group(0)       = ? 
    

    這是一個讓我覺得grep已退出中斷殺死tail前;如果它正在等待某件事,就會有跡象表明它收到了信號。

  4. 一個簡單的程序,模擬shell做什麼,但沒有等待,表明事情終止。

    #define _XOPEN_SOURCE 600 
    #include <stdlib.h> 
    #include <unistd.h> 
    #include <stdarg.h> 
    #include <errno.h> 
    #include <string.h> 
    #include <stdio.h> 
    
    static void err_error(const char *fmt, ...) 
    { 
        int errnum = errno; 
        va_list args; 
        va_start(args, fmt); 
        vfprintf(stderr, fmt, args); 
        va_end(args); 
        if (errnum != 0) 
         fprintf(stderr, "%d: %s\n", errnum, strerror(errnum)); 
        exit(1); 
    } 
    
    int main(void) 
    { 
        int p[2]; 
        if (pipe(p) != 0) 
         err_error("Failed to create pipe\n"); 
        pid_t pid; 
        if ((pid = fork()) < 0) 
         err_error("Failed to fork\n"); 
        else if (pid == 0) 
        { 
         char *tail[] = { "tail", "-f", "-n", "300", "qqq", 0 }; 
         dup2(p[1], 1); 
         close(p[0]); 
         close(p[1]); 
         execvp(tail[0], tail); 
         err_error("Failed to exec tail command"); 
        } 
        else 
        { 
         char *grep[] = { "grep", "-q", "return", 0 }; 
         dup2(p[0], 0); 
         close(p[0]); 
         close(p[1]); 
         execvp(grep[0], grep); 
         err_error("Failed to exec grep command"); 
        } 
        err_error("This can't happen!\n"); 
        return -1; 
    } 
    

    有了一個固定大小的文件,tail -f不會退出 - 這樣的外殼(bash)似乎流連。

  5. tail -n 300 -f qqq | grep -q return掛着,但是當我用另一個終端向文件qqq添加另外300行時,該命令退出。我解釋這是因爲grep已退出,所以當tail將新數據寫入管道時,它得到SIGPIPE並退出,因此bash認識到管道中的所有進程都已死亡。

我觀察到同樣的行爲與kshbash。這表明這不是一個錯誤,而是一些預期的行爲。在x86_64機器上的Linux(RHEL 5)上進行測試。

+4

不錯的分析!有趣的是,'grep -q pattern <(tail -f logfile)'工作得很好。 –

+0

@KolyolyHorvath爲什麼這還不是答案? –

3
tail -f logfile | grep --max-count=1 -q 'Message to continue' 

誠然,當讀取下一行,不會立即對匹配一個退出。

0

我正在爲我自己的項目尋找答案。嘗試測試VMware ESXi VM上傳遞的GPU是否處於活動狀態。同一個問題的多種變化無處不在。這是最近的。我想出了一個辦法來欺騙它,如果你可以在日誌中重複你感興趣的行,那麼:

tail -n 1 -f /var/log/vmkernel.log |的grep -m 1 IOMMUIntel >> /無功/日誌/ vmkernel.log

此尾部日誌,在每次一行,grep的檢查每一行第一次出現,並將其追加到日誌然後尾巴立即退出。

如果你像VMware passthough黑客攻擊,在這裏閱讀更多: http://hackaday.io/project/1071-the-hydra-multiheaded-virtual-computer