有没有办法在脚本内部使用 tee 和整个脚本?

有没有办法在脚本内部使用 tee 和整个脚本?

我正在编写一个脚本来更新系统(Ubuntu 22.04),使用一个命令(如sudo ./update.sh)更新 apt、flatpak 和 snap 中的所有软件包,并且如果出现问题,我想将输出保存在文件中。我有两种方法可以做到这一点。

一种是使用“tee”重定向每个订单的标准输出,例如:

echo "### apt update:\n" | tee update.out
apt update | tee -a  update.out

# etc, etc all with "| tee -a update.out"

这正是你在编程时想要避免的那种重复。

我可以做的另一种方法是使用“tee”调用脚本本身,如下所示:

sudo ./update.sh | tee update.out

但是如果我希望默认采用这种行为,那么明智的做法是将其放入脚本中,对吗?

我该怎么做呢?当我这样做时sudo ./update.sh,它会将整个输出发送到屏幕和输出文件?

答案1

你可以把这一行放在脚本的顶部:

exec &> >(tee -a "update.out")

例如:

#!/usr/bin/env bash

exec &> >(tee -a "update.out")

echo "this is going through tee"

答案2

笔记:如果你使用的是 Bash 或 Zsh 以外的 shell,则可能需要(以更便携的方式)替换|&2>&1 |

你可以将整个脚本包装在大括号并通过管道将输出传输至tee

Bash 提供了两种方法将要执行的命令列表分组为一个单元。将命令分组后,可以将重定向应用于整个命令列表。例如,可以将列表中所有命令的输出重定向到单个流。[...] 将命令列表放在花括号之间会导致在当前 shell 上下文中执行该列表。不会创建任何子 shell。列表后面的分号(或换行符)是必需的。

第一个例子仅用于你只想记录 stdout 的情况,并且不需要担心错误;请参阅第二个示例以获得更好的解决方案(此示例具有不保留输出文件中的 stderr 的不利/预期效果,以及不保留终端中 stdout / stderr 的顺序的不利效果,一般来说,我建议您只使用第二种方法,它将正常工作(tm)。

#!/usr/bin/env bash

{
        echo foo
        echo bar
} | tee log.log

exit 0
~ % ./script.sh   
foo
bar
~ % cat log.log 
foo
bar

这将记录 stdout 和 stderr,没有任何副作用

#!/usr/bin/env bash

{
        echo foo
        echo bar
        echo error >&2
} |& tee log.log

exit 0
~ % ./script.sh 
foo
bar
error
~ % cat log.log 
foo
bar
error

@bizmutowyszymon 的回答如果你想记录一切(整个脚本,包括 stdout 和 stderr)同时发送到终端和文件;使用此方法的优点是您可以有选择地决定将哪组命令发送到哪组:

#!/usr/bin/env bash

{
        echo This part shall be printed both to the terminal and to
        echo the
        echo file >&2
} |& tee log.log

echo But this part shall be printed only to the
echo terminal >&2

{ echo Here we output again to the both; } |& tee -a log.log

echo And this will just be printed to the file >>log.log

exit 0
~ % ./script.sh 
This part shall be printed both to the terminal and to
the
file
But this part shall be printed only to the
terminal
Here we output again to the both
~ % cat log.log 
This part shall be printed both to the terminal and to
the
file
Here we output again to the both
And this will just be printed to the file

相关内容