2017-03-09 7 views
2

私はいつかダミーエラーを出力するコンパイラを扱わなければなりません。私はその場合、私のビルドプロセスを止めたくありません。代わりに、私は単にエラーを無視して、コンパイラを再実行したい:

%o: %c 
    $(prefix) dumb_compiler -c $^ -o [email protected] $(suffix) 

私の目標は、ダミーのエラーを無視する$prefix$suffixとして何かを定義することです。代わりにdumb_compilerの者は、単にこのダミーのプログラムを考えてみましょう:

#!/usr/bin/perl 
my $i = int rand 10; 
die "Error -42\n" if $i > 5; 
die "Error -12\n" if $i % 2; 
print "$i\n"; 

Error -42が発生した場合、私はstdoutstderrを破棄し、何事もなかったかのように再度プログラムを実行したいです。それ以外の場合は、プログラムが印刷したものを印刷したい。

私はMakefileレシピにそれを置くためにonelinerとしてbashで次のように記述したいと思います:

while True: 
    (_exit, _stdout, _stderr) = exec(program) 
    if _exit == 0 and "Error -42" not in _stderr: 
     print(stdout=_stdout, stderr=_stderr) 
     exit(_exit) 

私は現在、これを書いたが、それは動作しません、それは似ていませんoneliner

#!/usr/bin/bash 
exit_status=0 
run=1 
exec 3>&1 
exec 4>&2 
while [ $run -eq 1 ]; 
do 
    run=0 
    ./program 2>&4 1>&3 
    $exit_status=$? 
    if [ $exit_status -ne 0 ] 
    then 
     &4 > grep -q "Error -42" 
     if [ $? -ne 0 ]: 
     then 
      run=1 
     fi 
    fi 
done 
3>&1 
4>&2 
3>&- 
4>&- 
exit $exit_status 

私の質問はどのように私はきちんと私のプログラムの実行から標準出力、標準エラー出力と終了ステータスを保持し、私が終わったら、それを洗い流すことができますか?

まだ私のプログラムの仕事をしようとすることはできますが、私のアプローチは間違っていると思います。

答えて

3

ファイルを使用してください。他のファイルハンドルへのリダイレクトは、(メモリ内またはディスク上の)何もバッファリングしません。彼らはここでの解決策ではありません。

while true; do 
    ./program > /tmp/output 2> /tmp/error && break 
    exit_status=$? 
    grep -q "Error -42" /tmp/error || break 
done 
cat /tmp/output 
cat /tmp/error >&2 
exit $exit_status 

この1つのマイナーな欠点は、標準出力と標準エラーがインターリーブされないことですが、それは大きな損失ではありません。それらは両方とも同じファイルハンドルに書き込むときにのみ「適切に」インターリーブされます。 (標準エラーError -42を検索したい場合は、のみ)、元のプログラムで作成された相対的な順序を保持できなくなりました。

+0

あなたの例では、最後の 'cat'は' program'の終了ステータスではなく '$?'を返します。私が間違っている? – nowox

+0

'/ tmp/output'、'/tmp/error'と一緒に '/ tmp'ディレクトリに侵入します。他のいくつかのプロセスが同じファイルを使用している場合、私は運命にある。そして、私はMakefileを '-j10'で実行するとこれが起こると思います。 – nowox

+0

@nowoxこれらの一時ファイルは単なる例に過ぎません。 'stdout = $(mktemp)'、 'stderr = $(mktemp)'などを使ってください。 – bishop

関連する問題