簡體   English   中英

tail -f | 找到數據后,awk和end tail

[英]tail -f | awk and end tail once data is found

我正在嘗試構建一個tail -f | awk的腳本 tail -f | awk每秒更新一次的日志文件。 awk部分將根據我的搜索參數僅獲取日志文件的必需部分。 輸出XML也在輸出文件中捕獲。 腳本工作正常 - 正如預期的那樣。

問題 - 然而,在執行搜索之后,由於tail -f而保持掛起。 任何想法如何更新下面的腳本 - 這樣一旦輸出XML被捕獲,它應該打破尾部?

XMLF=/appl/logs/abc.log

aa_pam=${1-xml}
[[ ${2-xml} = "xml" ]] && tof=xml_$(date +%Y%m%d%H%M%S).xml || tof=$2
tail -f $XMLF | \
awk  ' BEGIN { Print_SW=0; Cnt_line=1; i=0}
       /\<\?xml version\=/ { if (Print_SW==1) p_out(Cnt_Line,i)
                             Print_SW=0; Cnt_line=1;
       }
       { Trap_arry[Cnt_line++]=$0;
       }
       /'${1-xml}'/ { Print_SW=1;
       }
       /\<\/XYZ_999/    { if (Print_SW==1) p_out(Cnt_Line, i);
                             Print_SW=0; Cnt_line=1; }
       END { if (Print_SW==1) p_out(Cnt_Line, i); }
function p_out(Cnt_Line, i) {
       for (i=1;i<Cnt_line;i++) {print Trap_arry[i] | "tee '$tof'" }
}
' | tee $tof

更新嘗試按照以下使用exit建議 - 它成功存在腳本 - 但是在輸出中捕獲的xml正在重復。 所以在輸出文件中 - 相同的XML出現兩次.. !!

XMLF=/appl/logs/abc.log

aa_pam=${1-xml}
[[ ${2-xml} = "xml" ]] && tof=xml_$(date +%Y%m%d%H%M%S).xml || tof=$2
tail -f $XMLF | \
awk  ' BEGIN { Print_SW=0; Cnt_line=1; i=0}
       /\<\?xml version\=/ { if (Print_SW==1) p_out(Cnt_Line,i)
                             Print_SW=0; Cnt_line=1;
       }
       { Trap_arry[Cnt_line++]=$0;
       }
       /'${1-xml}'/ { Print_SW=1;
       }
       /\<\/XYZ_999/    { if (Print_SW==1) p_out(Cnt_Line, i);
                             Print_SW=0; Cnt_line=1; }
       END { if (Print_SW==1) p_out(Cnt_Line, i); }
function p_out(Cnt_Line, i) {
       for (i=1;i<Cnt_line;i++) {print Trap_arry[i] | "tee '$tof'" } { exit }
}
' | tee $tof

完成捕獲輸出后,調用exit (在終止前將跳轉到END塊)。

當awk終止時, tail -f對stdout的下一次write()將導致EPIPE錯誤。 tail知道在發生這種情況時終止。

更新:您似乎在嘗試決定退出的位置時遇到了一些問題。 它不應該在p_out因為您從結束XML標記匹配表達式 END塊中調用p_out 試試這個:

XMLF=/appl/logs/abc.log

aa_pam=${1-xml}
[[ ${2-xml} = "xml" ]] && tof=xml_$(date +%Y%m%d%H%M%S).xml || tof=$2
tail -f $XMLF | \
awk  '
  BEGIN {
    Print_SW=0
    Cnt_line=1
    i=0
  }

  /\<\?xml version\=/ {
     if (Print_SW==1)
        p_out(Cnt_Line,i)
     Print_SW=0
     Cnt_line=1
  }

  {
    Trap_arry[Cnt_line++]=$0
  }

  /'${1-xml}'/ {
    Print_SW=1;
  }

  /\<\/XYZ_999/ {
    if (Print_SW==1)
      p_out(Cnt_Line, i)
    Print_SW=0
    Cnt_line=1
    exit
  }

  END {
    if (Print_SW==1)
      p_out(Cnt_Line, i);
  }

  function p_out(Cnt_Line, i) {
    for (i=1;i<Cnt_line;i++) {
      print Trap_arry[i] | "tee '$tof'"
    }
  }
' | tee $tof

您可以在awk腳本中添加一行,例如:

/some-end-of-xml-marker/  {  close(/dev/stdin) ; }

我沒有嘗試過,但是你明白了:當你到達文件的末尾時關閉STDIN,這樣awk中的循環就會停止,你會到達END部分(沒有經過測試,我希望這證明是正確的。 ..)

基於這個問題如何在bash中打破tail -f命令你可以試試

#! /bin/bash

XMLF=/appl/logs/abc.log

aa_pam=${1-xml}
[[ ${2-xml} = "xml" ]] && tof=xml_$(date +%Y%m%d%H%M%S).xml || tof=$2

mkfifo log.pipe
tail -f "$XMLF" > log.pipe & tail_pid=$!

awk  -vpar1="$aa_pam" -vtof="$tof" -f t.awk  < log.pipe
kill $tail_pid
rm log.pipe

其中t.awk是:

/<\?xml version\=/ {
    if (Print_SW==1) {
        p_out(Cnt_Line)
    }
    Print_SW=0
    Cnt_line=0
}

{
    Trap_arry[++Cnt_line]=$0
}

$0 ~ par1 {
    Print_SW=1;
}

/<\/XYZ_999/    {
    if (Print_SW==1)
        p_out(Cnt_Line)
    Print_SW=0
    Cnt_line=0
}

function p_out(Cnt_Line, i) {
    for (i=1; i<Cnt_line; i++) {
        print Trap_arry[i] | ("tee " tof)
    }
    exit 1
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM