stdoutをスキップするための「exec >>(tee -ia $OUT)」オプションの生成

stdoutをスキップするための「exec >>(tee -ia $OUT)」オプションの生成

頑張る調整次のコンテンツを含むスクリプトを使用してください。

# first portion of script
# ...
exec > >(tee -ia $OUT)
# ...
# second portion of script 

このスクリプトの問題は、stdout(私の端末)に多くの出力を生成することです。スクリプト作成者には、端末出力を削除するオプションは含まれていません。私オプションを削除stdoutし、ファイルからのみ出力を取得します$OUT

私が試したことは次のとおりです。

TERM_OPT="OFF"

# first portion of script
# ...

if [ $TERM_OPT != "OFF" ]; then
     exec > >(tee -ia $OUT)
else {

# ...
# second portion of script 

} > $OUT
fi

うまくいくようですが、目的はわかりません。大きな括弧 {}この文脈では、グループコマンドのGNU部分良い;説明リストの後にはセミコロンが必要です。しかし、追加したり;削除したりしても違いはないようです。()中かっこの代わりにかっこを使うべきかどうか疑問に思います。ただし、これを行うと、すべての内容が()サブシェルで実行されます。他人の台本だからあまり気にしないのに&サブシェルそれが何を意味するのか明確ではありません(試してみたことはありません)。

私が試したもう一つのことのように見えるハッキングですが、他の人がそれを使っているという内容を読んで、うまくいくようです。

TERM_OPT="OFF"

# first portion of script
# ...

if [ $TERM_OPT != "OFF" ]; then
     exec > >(tee -ia $OUT)
else
     exec > >(tee -ia $OUT 1> /dev/null)
fi

# ...
# second portion of script 

これはもっと目立つので好きです。独立しかし、これは考慮する価値がありません。

質問は次のとおりです。 これを行う正しい方法は何ですか?つまり、正しい方法が何であるか退会exec > >(tee -ia $OUT)?これらの解決策の1つが他のものよりも優れていますか?それとも全く違うことをする必要がありますか?

答え1

ただ$OUT一時停止モードでファイルにリダイレクトする方がaはるかに簡単です。

case $TERM_OPT in
  (OFF) exec >> "$OUT";;
  (*)   exec > >(tee -ia -- "$OUT")
esac

シェルは終了を待たないため、スクリプトが完了した後も何かが出力され続けることteeがわかります。tee

$ bash -c 'exec > >(tee -ia -- file); echo A'; echo B; sleep 1
B
A

AB以降の出力を見てください。

この問題を解決するには、次を追加できます。

if [ "$TERM_OPT" != OFF ]; then
  exec > /dev/null # closes the pipe to tee which should cause tee
                   # to see EOF on input and exit
  wait # waits for all asynchronous tasks including tee
fi

スクリプトの終わりまたはEXITトラップにあります。

別のオプション(shでも機能)は、スクリプト全体をmain関数に入れて、次のことです。

#! /bin/sh -
main() {
  # your script here
}
case $TERM_OPT in
  (OFF) main "$@" >> "$OUT";;
  (*)   main "$@" | tee -ia -- "$OUT"
esac

答え2

ファイルに追加するためにstdoutをリダイレクトし、端末に出力コピーを保持したくない場合は、次の手順を実行します。

exec >> "$OUT"

唯一の目的teeは、1つのストリームを複数のストリームにコピーすることであるため、出力を1つの場所に配置したい場合は必要ありません。確かに作業することができtee -ia "$OUT" > /dev/nullますが、それは少し愚かなことです。他のコピーを破棄するために、まだ出力をコピーします。

{}この場合、中かっこを使用することは不明です。

中括弧にはセミコロンまたは改行文字が必要です。実際、マニュアルには次のように記載されています。「リストの後にはセミコロン(または改行)が必要です。」どちらの場合も、括弧は必要ありません。

サブシェルの意味は、サブシェルがシェルの独立したコピーで実行され、サブシェルのすべての変更が外部で表示されないことです。サブシェルの終わりにスクリプトも終了すると、あまり意味がありません。サブシェルが行うことは、不要なプロセスを開始することだけです。

私は次のようなものを選択します。

if [ "$TERM_OPT" != "OFF" ]; then
     exec > >(tee -ia -- "$OUT")
else
     exec >> "$OUT"
fi

関連情報