我只想将脚本的输出保存在脚本开头不知道的地方。我尝试了一些,但是我很确定它很丑。 有没有一种优雅的方法可以做到这一点:
#!/bin/bash
# Here I don't know where to write outputfile so I create a tmpfile
fic=$(mktemp -t)
trap 'rm -f $fic' EXIT
rm -f $fic
:> $fic
exec 3<> $fic
exec 1>&3
exec 2>&3
# some code in particular reading options and dest dir
echo foo
dir="."
# Here I finally know where I can write my output
fic2=$dir/log.log
cp -f $fic $fic2
exec 3>&- # close fd #3
exec 1>> $fic2
exec 2>&1
echo bar
此外,我想准备整个输出,例如$ exec ...>(tee $ fic)$,但是我找不到解决方案。
非常感谢您提供任何建议。 PJLM
答案 0 :(得分:1)
如果您知道两个输出文件都在同一文件系统上,则可以mv
来输出文件。您打开的文件描述符将继续起作用。
exec 1>/tmp/out1 2>&1
echo out1
mv /tmp/out1 /tmp/out2 # replace with your desired destination
echo out2
如果您想tee
的输出,并且两个输出文件都在同一文件系统上,则可以做几乎相同的事情(一旦tee
打开了用于写入的文件即使文件移动,也将继续写入相同的fd。
log1=$(mktemp)
exec 3>"$log1"
exec 1> >(tee /dev/fd/3) 2>&1
echo out1
mv "$log1" "$log2"
echo out2
请注意,我没有做>(tee "$log1")
,而是先在外壳中打开fd 3,然后使用>(tee /dev/fd/3)
。这是因为否则,在进入tee
步骤之前,mv
可能不会打开文件。 (exec
仅等待运行tee
的 subshell ,但是tee
本身需要花一些时间来启动和打开文件)。
如果您的第一个和第二个输出文件可能不在同一文件系统上,则必须进行一些更高级的改组,并确保在复制第一个文件之前完成对第一个文件的写入。 / p>
在简单重定向的情况下,我们需要在移动之前关闭文件描述符:
exec 1>"$log1" 2>&1
echo out1
exec 1>&- 2>&-
mv "$log1" "$log2"
exec 1>>"$log2" 2>&1
echo out2
如果用输出文件可能在不同文件系统上进行进程替换,我们需要确保在移动文件之前完成进程替换:
exec 3>&1 4>&2 # save original stdout, stderr
exec 1> >(tee "$log1") 2>&1 # redirect to tee
pid=$! # save pid of tee's subshell
echo out1
exec 1>&3 2>&4 # restore original stdout, stderr
# wait until tee is done. on newer bash can use `wait $pid` instead
while kill -0 $pid 2>/dev/null; do :; done
mv "$log1" "$log2"
# repeat steps above for new file
exec 3>&1 4>&2
exec 1> >(tee -a "$log2") 2>&1
pid=$!
echo out2
exec 1>&3 2>&4
while kill -0 $pid 2>/dev/null; do :; done