将单个输出写入终端,同时将其他所有内容发送到文件

将单个输出写入终端,同时将其他所有内容发送到文件

我用来exec将脚本的所有输出发送到文件:exec > file.errout 2>&1。但是,在脚本中间,我想向终端和文件发送几条消息。我找到了这段代码这里,但它需要在每个终端消息的两侧添加两行代码并通过管道传输到tee

exec > file.errout 2>&1
...
echo "messages only directed to the file"
...
exec >/dev/tty
echo "message i want directed to the terminal" | tee file.errout
exec > file.errout 2>&1
...
echo "more messages only directed to the file"
...

有没有更简单的方法来做到这一点?

答案1

您不必一定这样做。使用将所有标准输出内容放入文件后exec,只需将要放入终端的语句分组tee/dev/tty

exec > file.errout 2>&1

echo "messages only directed to the file"

{
    echo "message i want directed to the terminal and file" ;
    echo "more more message i want directed to the terminal and file" ;
} | tee /dev/tty

echo "more messages only directed to the file"

您不需要exec >/dev/tty每次都这样做,因为凭借您的初始exec行,所有标准输出都已记录到文件中。

答案2

在 bash 和 zsh 中,你可以尝试这样的操作:

exec >file.errout 2>&1
  # ...
exec {foo}>&1 > >(tee /dev/tty) 2>&1   # temporarily redirect
echo bla
ls no_such_file
exec >&$foo 2>&1                       # restore
  # ... 

重定向exec {var}>&1 ... exec >&$var/恢复与 类似exec 7>&1 .. exec >&7,只是 bash 本身会获取一个未使用的文件描述符并将其存储在变量中$var,而不是必须使用某个固定的数字,这可能与其余代码冲突。这种形式的重定向是 ksh 扩展,bash 和 zsh 也支持。

重定向exec > >(...)+进程替换组合虽然实用,但存在一些怪癖和错误(并且可能在 ksh93 中不起作用)。


当然,您可以将命令分组在一个{...}块中,并将整个块的输出重定向到管道| tee /dev/tty。这是最简单、最便携的。

它的问题是任何变量分配都将发生在子 shell 中,而不是在主脚本中:

a=before
{
   a=$(pwd)
   # ...
} | tee /dev/tty
echo "$a"  #  still "before"  

相关内容