【发布时间】:2021-08-06 08:11:17
【问题描述】:
有没有办法让脚本同时记录命令行运行(包括管道运行)及其输出,而无需复制命令的行?
目的是脚本应该有一个干净的输出,但应该详细地记录到一个日志文件中(所以没有set -x)。除了输出之外,它还应该记录导致输出的命令行,这可能是一个管道命令行。
最基本的方法是复制脚本中的命令行,然后将其转储到日志中,然后捕获正在运行的实际命令的输出:
echo "command argument1 \"quoted argument2\" | grep -oE \"some output\"" >> file.log
output="$(command argument1 "quoted argument2" 2>&1 | grep -oE "some output")"
echo "${output}" >> file.log
这有一个副作用,即需要为日志转义引用的部分,这可能会导致错误,从而导致混乱。
如果没有任何命令通过管道传输,则可以将命令行存储在一个数组中,然后“运行”该数组。
command=(command argument1 "quoted argument2")
echo "${command[@]}" >> file.log
output="$("${command[@]}" 2>&1)"
echo "${output}" >> file.log
虽然使用这种方法"quoted argument2" 会在日志中变为quoted argument2。
有没有办法(在 bash 中)实现这一点而不必复制命令?
【问题讨论】:
-
你试过
eval吗?类似cmd="..."; echo "$cmd" &>> file.log; eval "$cmd" &>> file.log。 -
eval对我来说仍然是个谜。所以,我通常很少使用它,因为我更喜欢在广泛使用它之前了解一个工具。我当然可以修补它并试一试。如果这解决了我打算做的事情,将会报告。谢谢! -
不过,请注意
eval。在这种情况下使用它可能不是最好的主意。顺便说一句,为什么不能按需打开和关闭-x选项? -
如果我启用了
-x,据我所知,它会将所有内容都输出到 STDOUT。这将不再为用户提供干净的输出。虽然我还没有尝试在命令替换中运行它,其中输出被捕获在变量中。但是,除了输出我真正想要的命令和结果之外,它还会在每行的开头引入新字符(即“+”)以及它本身(+ set +x)再次禁用它时。如果可能的话,我想避免这种情况。 -
我的建议是在你感兴趣的命令之前打开
-x,然后关闭。取消设置PS4会抑制+。所以PS4=; set -x; <your command>; set+x应该做几乎你想要的(除了set +x也会被记录)。当然,您必须使用一些exec <redirection>命令将其他所有内容重定向到其他地方。