1

2 つのコマンドを実行するスクリプトがあります。最初のコマンドは、データを一時ファイルに書き込みます。最初のコマンドがバックグラウンドで実行されている間に、2 番目のコマンドは awk にパイプします。2 番目のコマンドの awk は、一時ファイルからデータを読み取る必要がありますが、データが一時ファイルに書き込まれるよりも高速に独自のデータを解析しています。

次に例を示します。

#!/bin/bash

command1 > /tmp/data.txt &
# command1 takes several minutes to run, so start command 2 while it runs in the background
command2 | awk '
    /SEARCH/ {
        #Matched input so pull next line from temp file
        getline temp_line < "/tmp/data.txt"
    }
'

これは、awk が command2 からのデータを非常に高速に解析して command1 が追いつかない場合を除き、機能します。つまり、command1 が書き込みを完了する前に、awk が /tmp/data.txt から EOF を取得しています。

また、次のように、getline の周りにいくつかのチェックをラップしようとしました。

while ((getline temp_line < "/tmp/data.txt") < 0) {
    system("sleep 1") # let command1 write more to the temp file
}
# Keep processing now that we have read the next line

しかし、一時ファイルでEOFに達すると、それからの読み取りが停止すると思います。またはそのようなもの。

command1 が awk が一時ファイルから読み取ろうとするよりも速く一時ファイルに書き込む限り、スクリプト全体が機能します。2 つのコマンドの間に sleep 10 コマンドを挿入すると、一時ファイルによって十分なバッファーが作成され、スクリプトによって必要な出力が生成されます。しかし、私がテストしたものよりもはるかに大きなファイルを解析している可能性があるか、コマンドが異なるシステムで異なる速度で実行される可能性があるため、データが書き込まれるまでファイルを待機する安全メカニズムが必要です.

どうすればこれを行うことができますか?

4

1 に答える 1

1

繰り返しの間にファイルを閉じて、最初から以前に読んだ場所にもう一度読み込む必要があると思います。このようなものです(テストされていません)。

sleepTime = 0
while ((getline temp_line < "/tmp/data.txt") <= 0) {
    close("/tmp/data.txt")
    system("sleep " ++sleepTime) # let command1 write more to the temp file
    numLines = 0
    while (++numLines < prevLines) {
        if ( (getline temp_line < "/tmp/data.txt") <= 0 ) {
             print "Aaargghhh, my file is gone!" | "cat>&2"
             exit
        }
    }
}
++prevLines

変数「sleepTime」を組み込んで、ループのたびにコマンドをより長くスリープさせることに注意してください.tmpファイルがいっぱいになるのに時間がかかる場合、2番目のコマンドは反復ごとに長く待機します. それを使用するかどうかはお好みで。

入れ子になったループで system() コマンドを使用して getline を使用するのは、少しぎこちなく、エラーが発生しやすいようです。

于 2013-03-13T01:18:17.833 に答える