0

次のような AWK スクリプト内でネストされた getline を使用できるかどうか教えてください。

while ( ("tail -f log" |& getline var0) > 0) {

    while ( ("ls" | getline ) > 0) {
    }
    close("ls")
    while ( ("date" | getline ) > 0) {
    }
    close("date")
}
    close("tail -f log")

ネストされた getline 機能を利用できる深さはどのくらいですか? また、ネストされた getline のどのレベルでも出力のデータ損失はありますか? このスタイルを実装する際に確認すべきことは何ですか?

================================================== ================================

更新===================更新==============更新============= =アップデート=======

要件 : QAボックスとウェブサーバー/サービスのログとシステムステータスを精査して、リアルタイムの統計データとエラーを提供してください。レポートは次の形式で生成されます。

現地の日付と時刻 | カテゴリ| コンポーネント | 調子

仮定 -: AWK スクリプトはシェル スクリプトよりも高速に実行され、組み込みの解析やその他の機能を使用する利点が追加されます。

実装: - メイン コマンド ループは、command0="tail -f -n 0 -s 5 ..........." です。このコマンドは、追加されたサービスのログ/QA ボックスの Web サーバーを抽出する無限ループを開始します。. 追加されたすべてのデータをログにダンプし、各反復の後に 5 秒間スリープし、既存のログからデフォルトのコンテンツを出力せずに開始する -f、-s、および –n オプションに注意してください。

各反復の後、システム時間をキャプチャして検証し、10 秒間隔 (各反復の間に 5 秒間スリープし、テール出力を処理した後 4 秒間) 後にさまざまな OS リソース コマンドを実行します。すべてのテール コマンドの処理に約 1 秒かかると仮定すると、全部で 10 秒)

OS リソースを抽出するために使用したさまざまなコマンドは次のとおりです。

I.  command1="vmstat | nl | tr -s '\\t '"
II. command2="sar -W 0"
III.    command3="top -b -n 1 | nl | tr -s '\\t '"
IV. command4="ls -1 /tmp | grep EXIT"

スクリプト内の各コマンド(?)を検索し、スクリプト内のwhileループをたどって、各コマンドの出力処理を図ります。開発/コーディングを容易にするために「nl」コマンドを使用したことに注意してください

最終的に、ボックスに /tmp/EXIT ファイルが存在すると、ボックスから同じファイルを削除した後にスクリプトが終了します

以下は私のスクリプトです - 私は自明のために可能な限りコメントを追加しました:

#Useage - awk -f script.awk
BEGIN {
    command0="tail -f -n 0 -s 5 /x/web/webserver/*/logs/error_log /x/web/webserver/service/*/logs/log"
    command1="vmstat | nl | tr -s '\\t '"
    command2="sar -W 0"
    command3="top -b -n 1 | nl | tr -s '\\t '"
    command4="ls -1 /tmp | grep EXIT"
    format = "%a %b %e %H:%M:%S %Z %Y"
    split("", details)
    split("", fields)
    split("", data)
    split("", values)
    start_time=0

    printf "\n>%s:\n\n", command0 #dummy print for debuggng command being executed

    while ( (command0 |& getline var0) > 0) { #get the command output
        if (start_time == 0) #if block to reset the start_time variable
        {
                start_time = systime() + 4
        }
        if (var0 ~ /==>.*<==/) { #if block to extract the file name from the tail output - outputted in '==>FileName<==' format
                gsub(/[=><]/, "", var0)
                len = split(var0, name, "/")
                if(len == 7) {file = name[5]} else {file = name[6]}
        }
        if (len == 7 && var0 ~ /[Ee]rror|[Ee]xception|ORA|[Ff]atal/) {  #extract the logs error statements
                print strftime(format,systime()) " | Error Log | " file " | Error :" var0
        }
        if(systime() >= start_time) #check if curernt system time is greater than start_time as computed above
        {
                start_time = 0 #reset the start_time variable and now execute the system resource command
                printf "\n>%s:\n\n", command1
                while ( (command1 |& getline) > 0) { #process output of first command
                if($1 <= 1)
                        continue #not needed for processing skip this one
                if($1 == 2) #capture the fieds name and skip to next line
                {
                        for (i = 1; i <= NF; i++){fields[$i] = i;}
                        continue
                }
                if ($1 == 3) #store the command data output in data array
                        split($0, data);
                print strftime(format,systime()) " | System Resource | System | Time spent running non-kernel code :" data[fields["us"]]
                print strftime(format,systime()) " | System Resource | System | Time spent running kernel code :" data[fields["sy"]]
                print strftime(format,systime()) " | System Resource | System | Amount of memory swapped in from disk :" data[fields["si"]]
                print strftime(format,systime()) " | System Resource | System | Amount of memory swapped to disk :" data[fields["so"]]
                }
                close(command1)

                printf "\n>%s:\n\n", command2 #start processing second command
                while ( (command2 |& getline) > 0) {
                        if ($4 ~ /[0-9]+[\.][0-9]+/) #check for 4th positional value if its format is of "int.intint" format
                        {
                                if( $4 > 0.0) #dummy check now to print if page swapping
                                        print strftime(format,systime()) " | System Resource | Disk | Page rate is > 0.0 reads/second: " $4
                        }
                }
                close(command2)

                printf "\n>%s:\n\n", command3 # start processing command number 3
                while ( (command3 |& getline ) > 0) {
                        if($1 == 1 && $0 ~ /load average:/) #get the load average from the output if this is the first line
                        {
                                split($0, arr, ",")
                                print strftime(format,systime())" | System Resource | System |" arr[4]
                        }
                        if($1 > 7 && $1 <= 12) # print first top 5 process that are consuming most of the CPUs time
                        {
                                f=split($0, arr, " ")
                                if(f == 13)
                                        print strftime(format,systime())" | System Resource | System | CPU% "arr[10]" Process No: "arr[1] - 7" Name: "arr[13]
                        }
                }
                close(command3)
                printf "\n>%s:\n\n", command4 #process command number 4 to check presence of file
                while ( (command4 |& getline var4) > 0) {
                        system("rm -rf /tmp/EXIT")
                        exit 0 #if file is there then remove the file and exit this script execution
                }
                close(command4)
        }
    }
        close(command0)
}

出力 -:

>tail -f -n 0 -s 5 /x/web/webserver/*/logs/error_log /x/web/webserver/service/*/logs/log:


>vmstat | nl | tr -s '\t ':

Sun Dec 16 23:05:12 PST 2012 | System Resource | System | Time spent running non-kernel code :9
Sun Dec 16 23:05:12 PST 2012 | System Resource | System | Time spent running kernel code :9
Sun Dec 16 23:05:12 PST 2012 | System Resource | System | Amount of memory swapped in from disk :0
Sun Dec 16 23:05:12 PST 2012 | System Resource | System | Amount of memory swapped to disk :2

>sar -W 0:

Sun Dec 16 23:05:12 PST 2012 | System Resource | Disk | Page rate is > 0.0 reads/second: 3.89

>top -b -n 1 | nl | tr -s '\t ':

Sun Dec 16 23:05:13 PST 2012 | System Resource | System | load average: 3.63
Sun Dec 16 23:05:13 PST 2012 | System Resource | System | CPU% 12.0 Process No: 1 Name: occworker
Sun Dec 16 23:05:13 PST 2012 | System Resource | System | CPU% 10.3 Process No: 2 Name: occworker
Sun Dec 16 23:05:13 PST 2012 | System Resource | System | CPU% 6.9 Process No: 3 Name: caldaemon
Sun Dec 16 23:05:13 PST 2012 | System Resource | System | CPU% 6.9 Process No: 4 Name: occmux
Sun Dec 16 23:05:13 PST 2012 | System Resource | System | CPU% 6.9 Process No: 5 Name: top

>ls -1 /tmp | grep EXIT:
4

1 に答える 1

6

これは、この方法で getline を使用したことを思い出すことができる 2 番目の投稿です。前回、それは間違ったアプローチだと言いましたが、あなたは私を信じていなかったようですので、もう一度試してみましょう。

「awkを使用してgetlineでコマンドを実行し、出力を読み取るにはどうすればよいですか?」という質問。「ドリルを使ってガラスを切るにはどうすればいいですか?」と尋ねるようなものです。ガラスの破砕を避けるためにドリルで穴を開ける部分にテープを貼るようにという回答を得ることができます。それはあなたの質問に答えるでしょうが、より有用な答えはおそらく-それをしないで、ガラスカッターを使用することです. .

コマンドを呼び出すシェルとして awk を使用することは、100% 間違ったアプローチです。適切な仕事に適切なツールを使用するだけです。テキスト ファイルを解析する必要がある場合は、awk を使用します。ファイルやプロセスを操作したり、コマンドを呼び出したりする必要がある場合は、シェル (または OS の同等のもの) を使用します。

最後に、http://awk.freeshell.org/AllAboutGetlineを読んでください。すべての注意事項を完全に理解するまでは、getline の使用について考えないでください。

編集:投稿されたawkスクリプトが行うことを行うシェルスクリプトは次のとおりです。

tail -f log |
while IFS= read -r var0; do
    ls
    date
done

シンプルに見えますか?それをするのが理にかなっているとは言いませんが、やりたいのであれば、awkではなく、それが実装方法です。

編集: awk スクリプトの最初の部分をシェル (この場合は bash) で記述する方法は次のとおりです。残りの部分を翻訳する熱意が尽きたので、残りを自分で行う方法を示していると思います。

format = "%a %b %e %H:%M:%S %Z %Y"
start_time=0

tail -f -n 0 -s 5 /x/web/webserver/*/logs/error_log /x/web/webserver/service/*/logs/log |
while IFS= read -r line; do

    systime=$(date +"%s")

    #block to reset the start_time variable
    if ((start_time == 0)); then
        start_time=(( systime + 4 ))
    fi

    #block to extract the file name from the tail output - outputted in '==>FileName<==' format
    case $var0 in
        "==>"*"<==" )
            path="${var0%% <==}"
            path="${path##==> }"
            name=( ${path//\// } )
            len="${#name[@]}"
            if ((len == 7)); then
                file=name[4]
            else
                file=name[5]
            fi
            ;;
    esac

    if ((len == 7)); then
        case $var0 in
            [Ee]rror|[Ee]xception|ORA|[Ff]atal )    #extract the logs error statements
                printf "%s | Error Log | %s | Error :%s\n" "$(date +"$format")" "$file" "$var0"
                ;;
        esac
    fi

    #check if curernt system time is greater than start_time as computed above
    if (( systime >= start_time )); then

        start_time=0 #reset the start_time variable and now execute the system resource command
        ....

これは awk スクリプトよりもわずかに高速に実行されることに注意してください。ただし、テールは反復の間に 5 秒間の休憩を取っているため、まったく問題にはなりません。

また、上記で行っているのは awk スクリプトをシェルに変換することだけであることにも注意してください。必ずしも、このツールをゼロから作成するのが最善の方法であるとは限りません。

于 2012-12-14T13:43:14.007 に答える