如何创建文件描述符 stdout 和 stderr 的真实副本,而不使用 unbuffer / script / tee 仅使用 bash 内置函数?

如何创建文件描述符 stdout 和 stderr 的真实副本,而不使用 unbuffer / script / tee 仅使用 bash 内置函数?

我的目标是将应用程序 ( ) 的所有输出 (stdout和)复制、重定向到一个文件,同时保留应用程序 ( )和的通常行为。stderrapt-getapt-getstdoutstderr

如何创建文件描述符stdout和的真实副本stderr?我希望保持stdoutstderr尽可能“自然”。例如,如果它正在运行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)

unbuffer是否可以在没有//scripttee使用bash内置函数的情况下实现这一目标?

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

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


[1]

22% [8 Packages 3,449 kB/7,098 kB 49%]
174 kB/s 4min 57s

答案1

POSIXshell 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
}

bash在一个存在的文件上测试它ls(输出一行到标准输出),以及一个不存在的文件名(输出另一行到标准错误错误率):

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

输出:

/bin/bash
ls: cannot access '/bin/nosuchfile': No such file or directory

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

ls /bin/dash /bin/nohowsuchfile  1>  >(faketee -a std.log) \
                                 2>  >(faketee -a err.log >&2)

输出:

/bin/dash
ls: cannot access '/bin/nohowsuchfile': No such file or directory

现在检查日志文件以查看是否-a待定开关工作原理:

grep -n '.' std.log err.log

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

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

相关内容