
stdoutを「特定のコードブロック」に直接パイプし、変更されたデータをファイルに書き込むと、tee
常にファイルから予想される出力行の完全な補完が得られます。
ただし、tee
同じデータをプロセスに送信すると、>("same block of code")
出力から最大4行が削除される可能性があります。この数字はさまざまで、時にはすべての行を作成します。
この問題をどのように解決できるか、なぜでのみ発生しますか>( process )
?
追加情報:この回線損失が発生したとき、私は通常のstdoutパイプだけでなく、2つのプロセス置換を「ティーイング」していました。
Ubuntu 10.04.2 LTS、バージョン4.1.5(1)リリース(i486-pc-linux-gnu)でGNU bashを使用します。
これが実際のスクリプトです。 2番目のプロセスの置き換えは問題のプロセスです。>(tr $'\x60' $X01
#
# Run 'locate' and direct the output to a temp file
errflag=""
locitmct=0 # Count of located items
columns=4 # The number of columns in the main dialog
colmnb=0 # Column number (NB: columns 1 and 2 are processed together)
X01=$'\x01'
eval locate $zenargs |tee \
>(zenity --progress --pulsate --auto-close) \
>(tr $'\x60' $X01 \
|sed -n "s/^\(.*\/\)\(.*\)/\1\2\n\2\n\1/p" \
|while IFS= read -r line ; do \
#
#
# process the data
#
#
done > "$listf" )\
>/dev/null
#
cat "$listf"
#
答え1
この質問をしてから10時間が経過し、解決策が見つかりましたwait
。これは、これらの「プロセスオーバーライド」が待っている「サブ」プロセスではないためだと思いますwait
。 (パラメータなしで試しましたwait
)....
機能や欠点についてご意見をいただきありがとうございます。 stdinがどのように選択さzenity
れ、最初のコマンドがtr
いつecho
であるかはよくわかりませんが、試してみたかったのですが...これはうまくいくようですが、このアプローチは安全ですか?
この問題を解決するためによく試され、テストされた方法がある可能性があるため、他の答えはそれほど価値があります。
#!/bin/bash
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# Set up flag-files for processes to send PIDs to main process
# The first thing each process does is: echo -n "$BASHPID " > flag-file
for i in {1..2};do cp /dev/null "$listf".pid$i;done
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
eval locate $zenargs |tee \
>(echo -n "$BASHPID " > "$listf".pid1 ; \
zenity --progress --pulsate --auto-close) \
>(echo -n "$BASHPID " > "$listf".pid2 ; \
tr $'\x60' $X01 \
|sed -n "s/^\(.*\/\)\(.*\)/\1\2\n\2\n\1/p" \
|while IFS= read -r line ; do \
#
#
# process the data
#
#
done > "$listf" ) \
>/dev/null
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#### WAIT for processes to terminate
pids=$(cat "$listf".pid{1,2})
while [[ "$pids" == *[0-9]* ]] ; do
sleep .1 # GNU
for pid in $pids ; do
if ! kill -0 "$pid" 2>/dev/null; then
pids="${pids/$pid/}"
fi
done
done
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
cat "$listf"
#
答え2
coreutilsバージョン8.24以降、さまざまな方法があります。
tee -p </dev/zero >(head -c10M | wc -c ) > >(head -c1 | wc -c ) | numfmt --to=iec
出力は次のとおりです
1
10M
ここで重要なポイントは
これを使用すると、パイプにエラーではなくすべての出力に警告が記録され
-p
ます。tee
つまり、EPIPEエラーは終了をfwrite
引き起こさず、書き込み用に開いている出力ファイルが1つ以上ある限り実行されます。 stderrで印刷することについてEPIPE警告を受け取るには。tee
tee
--output-error=warn
-p
> >(head -c1 | wc -c )
teeの標準出力を別の出力にリダイレクトするために使用されます>(process substitution)
。これは2つの理由で重要です。たとえば、stdinを使用している場合はstdinにデータがある限り実行されます(この場合は永久に実行されます)tee
。同時に、さらなる処理のために出力を標準出力に送ることができる。あまりエレガントではありませんが、別の可能性は別の方法でstdout出力をオフにすることです。 2つの可能性はとです。ただし、これは警告を発行します(tee:stdout:デバイスに残りのスペースがなくなり、tee:stdout:それぞれ無効なファイル記述子)。>/dev/null
tee
>(process substitution)
tee
>/dev/full
>&-