如何在不使用 unbuffer / script / tee 的情况下仅使用 bash 内置程序创建文件描述符 stdout 和 stderr 的真实副本?

adr*_*nos 5 scripting shell-script tee stdout stderr

我的目标是将应用程序 ( ) 的所有输出 (stdout和stderr)复制、重定向apt-get到文件,同时保留应用程序 ( apt-get)stdout和stderr.

如何创建文件描述符stdout和的真实副本stderr?我想继续stdout和stderr“天然”成为可能。例如apt-get,如果它正在运行,我希望保留颜色和进度信息。[1]

这是一个例子。(包装器可以做更多的事情,只是保持简单。)

#!/bin/bash

temp_dir="$(mktemp --directory)"
logfile="$temp_dir/log"

unbuffer apt-get "$@" 1> >(tee -a "$logfile") 2> >(tee -a "$logfile" >&2)
Run Code Online (Sandbox Code Playgroud)

是否有可能实现这一目标,而不unbuffer/ script/tee只是bash内置插件?

(为了使包装器更简单并依赖更少的外部二进制文件。否则这可能会导致与强制访问控制等发生冲突。)

(其手册页不鼓励在非交互式脚本中使用script(1)。)


[1]

22% [8 Packages 3,449 kB/7,098 kB 49%]
174 kB/s 4min 57s
Run Code Online (Sandbox Code Playgroud)

agc*_*agc 0

这个POSIX shell faketee函数没有依赖项:

faketee() {
   if [ "$1" = '-a' ] ; then 
      shift
      while read -r x ; do 
         echo "$x" >> "$1"
         echo "$x"
      done
   else  
      while read -r x ; do 
         echo "$x" > "$1"
         echo "$x"
      done
   fi
}
Run Code Online (Sandbox Code Playgroud)

bash使用ls存在的文件(将一行输出到STDOUT)和不存在的文件名(将另一行输出到STDERR)进行测试:

cd /tmp
ls /bin/bash /bin/nosuchfile  1>  >(faketee -a std.log) \
                              2>  >(faketee -a err.log >&2)
Run Code Online (Sandbox Code Playgroud)

输出:

/bin/bash
ls: cannot access '/bin/nosuchfile': No such file or directory
Run Code Online (Sandbox Code Playgroud)

...然后使用另外两个这样的文件名再次运行它:

ls /bin/dash /bin/nohowsuchfile  1>  >(faketee -a std.log) \
                                 2>  >(faketee -a err.log >&2)
Run Code Online (Sandbox Code Playgroud)

输出:

/bin/dash
ls: cannot access '/bin/nohowsuchfile': No such file or directory
Run Code Online (Sandbox Code Playgroud)

现在检查日志文件以查看pend开关是否工作:-a

grep -n '.' std.log err.log
Run Code Online (Sandbox Code Playgroud)

输出表明附加的重定向位于应有的位置:

std.log:1:/bin/bash
std.log:2:/bin/dash
err.log:1:ls: cannot access '/bin/nosuchfile': No such file or directory
err.log:2:ls: cannot access '/bin/nohowsuchfile': No such file or directory
Run Code Online (Sandbox Code Playgroud)