创建输出到多个目标的文件描述符
Create file descriptor which outputs to multiple targets
我正在写一个脚本,它的大部分输出最好发送到日志文件,但我想 'opt in' 某些命令到控制台输出,例如显式脚本 status/feedback 条消息。
我创建了三个命名文件描述符:一个用于终端,一个用于日志,还有一个同时用于终端和日志。我曾尝试使用 tee
将输入发送到 $both
并使其到达 $term
和 $log
,但这似乎具有重新排序输出的效果。有没有办法实现上述但保留输出顺序?
# Create FD 'term' with target == stdout's current target
exec {term}>&1
# Create FD 'log' with target == ./my-log.txt
exec {log}>"$log_path"
# Attempt to use tee to split output off into $log FD and send stdout to $term FD
exec {both}> >(tee -a "/dev/fd/$log" 1>&$term)
# Set stdout and stderr to route to $log FD
exec 1>&$log 2>&$log
echo 1 - example output of command
1>&$both echo 2 - script feedback/status
echo 3 - example output of command
1>&$both echo 4 - script feedback/status
echo 5 - example output of command
# stdout:
# 2 - script feedback/status
# 4 - script feedback/status
# $log_path:
# 1 - example output of command
# 3 - example output of command
# 5 - example output of command
# 2 - script feedback/status
# 4 - script feedback/status
谢谢
问题是,当您将输出发送到 both
时,bash
不会等到 tee
实际写出它才移到下一行,所以您以 bash
和 tee
的竞争条件结束,对 log
进行不同步写入。除非你有充分的理由需要一个 FD,否则最简单和最好的解决方案可能就是这样做:
exec {term}>&1 >"$log_path" 2>&1
echo 1 - example output of command
echo 2 - script feedback/status | tee "/dev/fd/$term"
echo 3 - example output of command
echo 4 - script feedback/status | tee "/dev/fd/$term"
echo 5 - example output of command
根据另一个答案,你可以进一步定义echo2
函数:
echo2(){
echo "$@" | tee "/dev/fd/$term"
}
exec {term}>&1 >"$log_path" 2>&1
echo 1 - example output of command
echo2 2 - script feedback/status
echo 3 - example output of command
echo2 4 - script feedback/status
echo 5 - example output of command
我正在写一个脚本,它的大部分输出最好发送到日志文件,但我想 'opt in' 某些命令到控制台输出,例如显式脚本 status/feedback 条消息。
我创建了三个命名文件描述符:一个用于终端,一个用于日志,还有一个同时用于终端和日志。我曾尝试使用 tee
将输入发送到 $both
并使其到达 $term
和 $log
,但这似乎具有重新排序输出的效果。有没有办法实现上述但保留输出顺序?
# Create FD 'term' with target == stdout's current target
exec {term}>&1
# Create FD 'log' with target == ./my-log.txt
exec {log}>"$log_path"
# Attempt to use tee to split output off into $log FD and send stdout to $term FD
exec {both}> >(tee -a "/dev/fd/$log" 1>&$term)
# Set stdout and stderr to route to $log FD
exec 1>&$log 2>&$log
echo 1 - example output of command
1>&$both echo 2 - script feedback/status
echo 3 - example output of command
1>&$both echo 4 - script feedback/status
echo 5 - example output of command
# stdout:
# 2 - script feedback/status
# 4 - script feedback/status
# $log_path:
# 1 - example output of command
# 3 - example output of command
# 5 - example output of command
# 2 - script feedback/status
# 4 - script feedback/status
谢谢
问题是,当您将输出发送到 both
时,bash
不会等到 tee
实际写出它才移到下一行,所以您以 bash
和 tee
的竞争条件结束,对 log
进行不同步写入。除非你有充分的理由需要一个 FD,否则最简单和最好的解决方案可能就是这样做:
exec {term}>&1 >"$log_path" 2>&1
echo 1 - example output of command
echo 2 - script feedback/status | tee "/dev/fd/$term"
echo 3 - example output of command
echo 4 - script feedback/status | tee "/dev/fd/$term"
echo 5 - example output of command
根据另一个答案,你可以进一步定义echo2
函数:
echo2(){
echo "$@" | tee "/dev/fd/$term"
}
exec {term}>&1 >"$log_path" 2>&1
echo 1 - example output of command
echo2 2 - script feedback/status
echo 3 - example output of command
echo2 4 - script feedback/status
echo 5 - example output of command