パイプを使用せずに標準出力を端末とファイルにリダイレクトしますか?

パイプを使用せずに標準出力を端末とファイルにリダイレクトしますか?

次のコードがあります。

#!/bin/bash

VAR=0

func() {
    VAR=$((VAR+1))
    echo 'Logging information.'
}

func 2>&1 | tee 'log.txt'

echo "Should be 1: ${VAR}"

呼び出されると、次のことが発生します。

:~$ ./script.sh
Should be 1: 0

私が理解したのは、私が使用しているパイプラインがサブシェルを生成するためです。 in への変更はVAR上向きに伝播されないため、出力に反映されません。

func私の場合、プロセスはやや長く、出力はリアルタイムで行わなければなりませんでした。したがって、ファイルに書き込んでからcatそのファイルを読むことはオプションではありません。また、可能であればファイルに何も書かずに変数で読み直すことを避けたいと思います。

それでは、パイプの必要性を満たす方法はありますか?それとも私がまだ知らないのに役立つbashトリックはありますか?

編集する:

名前付きパイプを試してください。

#!/bin/bash

VAR=0

func() {
        VAR=$((VAR+1))
        echo 'Logging information.'
        sleep 5
}

mkfifo my_fifo

func >my_fifo 2>&1 &

tee 'log .txt' <my_fifo

echo "Should be 1: ${VAR}"

残念ながら、結果は同じです。

:~$ ./script.sh
Should be 1: 0

ベストアンサー1

次のことができます。

func > >(tee log.txt) 2>&1
wait

ロギング専用のファイル記述子を指定できます。

exec 3> >(tee log.txt)
tee_pid=$!

func >&3 2>&1
...

ただし、teeバックグラウンドで実行されるため、すべての出力が通過しないと、出力順序が影響を受ける可能性があります。

おすすめ記事