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)
这个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)