-->

捕获标准输出到一个变量,但仍然在控制台中显示它(Capture stdout to a variab

2019-06-18 04:40发布

我有一个bash脚本调用几个长期运行的流程。 我想这些调用的输出捕捉到了处理的原因变量。 但是,因为这些都是长时间运行的进程,我想rsync的输出要求实时和而不是在事后被显示在控制台中。

为此,我发现做这件事的方式,但它依赖于文本输出到/ dev /标准错误。 我觉得,输出到/ dev /标准错误不是一个做事的好方法。

VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee /dev/stderr)

VAR2=$(rsync -r -t --out-format='%n%L' --delete -s /path/source1/ /path/target1 | tee /dev/stderr)

VAR3=$(rsync -r -t --out-format='%n%L' --delete -s /path/source2/ /path/target2 | tee /dev/stderr)

在上面的例子中,我打电话rsync的几次,我希望看到他们正在处理的文件名,但最终我还是想在一个变量的输出,因为我将在后面分析它。

有没有实现这一点的“清洁”的方式?

如果它的确与众不同,我使用Ubuntu 12.04,庆典4.2.24。

Answer 1:

复制和在你的shell 1(在我examle 5),并在子shell使用&5(这样你就写信给父shell的标准输出(1)):

exec 5>&1
FF=$(echo aaa|tee >(cat - >&5))
echo $FF

将打印AAA两次,因为在子shell回声,和第二次的那些打印变量的值。

在您的代码:

exec 5>&1
VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee >(cat - >&5))
# use the value of VAR1


Answer 2:

运德Cirkel的回答有正确的想法。 它可以更加简化(避免使用的cat ):

exec 5>&1
FF=$(echo aaa|tee /dev/fd/5)
echo $FF


Answer 3:

这里有一个例子都捕捉stderr和命令的退出代码。 这是建立在由罗素·戴维斯答案。

exec 5>&1
FF=$(ls /taco/ 2>&1 |tee /dev/fd/5; exit ${PIPESTATUS[0]})
exit_code=$?
echo "$FF"
echo "Exit Code: $exit_code"

如果文件夹/taco/存在,这将捕获的内容。 如果该文件夹不存在,它会捕获错误消息,并且退出代码为2。

如果省略了2>&1那么只有stdout将被捕获。



Answer 4:

您可以使用三个以上的文件描述符。 试一下:

http://tldp.org/LDP/abs/html/io-redirection.html

“每个打开的文件被分配的文件描述符。[2]标准输入,stdout和stderr文件描述符是0,1,和2中。为了打开其他文件,仍然存在描述符3-9有时有用分配这些额外的文件描述符的一个标准输入,标准输出,或标准错误作为临时复制链接“。

问题的关键是,它是否值得,使脚本更复杂正好可以达到这种效果。 其实这不是真的错了,你的方式做到这一点。



Answer 5:

如果“控制台”你的意思是你目前的TTY,尝试

variable=$(command with options | tee /dev/tty)

这是稍有可疑的做法,因为人谁尝试使用这有时是当输出焊盘的地方意外时,他们没有一个TTY(cron作业等)感到惊讶。



Answer 6:

替代使用/dev/tty ,或者由其他的答案提出另外一个文件描述符,你也可以将其翻转,并简单地用一个临时文件。 这无疑是更容易阅读,更便于携带在某些情况下。

tmpFile=$(mktemp)  # mak-a de temp
rsync /a /b | tee $tmpFile # sync my b*tch up
if grep "U F'd up" $tmpFile; then
  rm -rf / #Seppuku
fi


文章来源: Capture stdout to a variable but still display it in the console