2016-11-12 11 views
1

出力メッセージを生成するBashスクリプトが必要です。スクリプトは、メッセージをキャプチャし、いくつかのフィルタリングを行い、変換し、スクリーンに出力することになっています。シェルスクリプト出力自体をフィルタリングすると、スクリプトは終了しません

フィルタ結果は出力では正しいですが、スクリプトは終了しません。私はそれを終了するためにリターンキーを押す必要があります。どうすれば修正できますか?

デモスクリプト:

#!/bin/bash 

exec &> >( 
     { 
     while read line; do 
      [ "$line" = "exit" ] && break 
      echo "`date +%H:%M:%S.%N` $line" 
     done 
     echo "while finish" 
     }) 

for ((i=3;i--;)); do 
    echo "text $i" 
done 

echo "exit" 
+0

説明を改善しようとしました。今それは...受け入れられるように見える。しかし、あなたが何を意味するかはまだ分かりません。 –

+0

http://stackoverflow.com/q/40564647/1030675 – choroba

答えて

1

スクリプト残し、、出力をが終了するが、スクリプト自体は出力を書き込み、バックグラウンド・プロセスを行う前に完了するので、プロンプトが最初に表示され、んあなたの端末はのように見えますが、のようなスクリプトはまだ実行されています。 returnを押す代わりに任意のコマンドを入力すると、そのコマンドが実行されます。

これを避けるには、スクリプトを終了する前に待機できる明示的なバックグラウンドジョブでwhileループを実行する必要があります。

mkfifo logpipe 
trap 'wait $logger_pid; rm logpipe' EXIT 

while read line; do 
    [ "$line" = "exit" ] && break 
    echo "$(date +%H:%M:%S.%N) $line" 
done < logpipe & 
logger_pid=$! 

exec &> logpipe 

# ========== 

for ((i=3;i--;)); do 
    echo "text $i" 
done 

echo "exit" 

whileループは、名前付きパイプlogpipeから入力を読み取り、バックグラウンドで実行されます。これが実行されると、すべての出力をパイプにリダイレクトして、「メイン」スクリプトを開始することができます。出口トラップは、whileループが完了するまでスクリプトが実際に終了しないようにします。あなたの名前付きパイプもクリーンアップします。


あなたがまだ気づいていないかもしれないが、whileループは物事がそれらに記述された正確な順序でマージされ、標準出力と標準エラー出力を受け取るという保証はありません。例えば、

echo out1 
echo err1 >&2 
echo out2 
echo err2 >&2 

out1 
err1 
err2 
out2 

ように、各ストリーム自体を読まれてしまうことがあり、順番に残るが、二つの任意マージすることができました。

関連する問題