2017-11-04 3 views
0

私は次のスクリプトがありますmy-binaryがkillされたときに "tee /tmp/my.log | my-binary"がすぐに終了しないのはなぜですか?

#!/bin/bash 
set -e 
set -o pipefail 
tee /tmp/my.log | my-binary 

my-script.sh ...次のように実行します。私のバイナリクラッシュやが殺されたとき

$ cat my-data.txt | my-script.sh 

私は仮定し、 のコピーteeのコピーはただちに終了する必要があります。ただし、シェル自体は終了しますが、teeはありません。

+1

他の誰かが問題を再現せるのに十分ではありません。特定の信号を「殺す」? 'my-binary 'が終了以外の方法でシグナルを処理することを選択した場合、シグナルをトラップすることができます。 –

+0

( 'pipefail'は、* tee *が失敗したが、* my-binary *が成功して終了した場合に終了ステータスが失敗したことを確認しますが、失敗した' my-binary'の場合は 'pipefail'は何の効果もありません)。 –

+0

... 'set -e'は、ほとんどの状況では[移植性の問題](https://www.in-ulm.de/~mascheck/various/set-e/)のソースでもありません。 )と[general nonintuitiveness](http://mywiki.wooledge.org/BashFAQ/105)(急いでいると練習を見て、アレゴリーをスキップします)。 –

答えて

1

The POSIX specification for teeは、指定されたオペランド(たとえば/tmp/my.log)への書き込みに失敗すると、teeコマンドは他の出力への書き込みを続ける必要があることを指定します。

この仕様を満たすために、teeの一般的な実装(GNU実装とBusyboxを含む)は、SIGPIPEを完全に無視します。これにより、早く終了する名前付きパイプの場合でも、操作を続行することができます(/tmp/my.log)。 SIGPIPE信号の副作用として

- は、無視され、teeを直ちにmy-binaryのSTDINへの出力が閉じているときに気づく、むしろ通知後ない - FIFOの他端はアボートとき受信しました試行された書き込みが失敗したとき。


すぐteeを殺すことは、重要であるとあなたがbashの4.4以降を実行している場合は、私が代わりに次の実装をお勧め:

#!/usr/bin/env bash 

# replace stdin with a pipe from tee 
exec < <(tee /tmp/my.log) 

# collect PID for the process substitution; REQUIRES BASH 4.4 OR NEWER 
tee_pid=$! 
trap 'kill "$tee_pid"' EXIT 

my-binary 
関連する問題