次のコードがあります。
#!/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
バックグラウンドで実行されるため、すべての出力が通過しないと、出力順序が影響を受ける可能性があります。