我有一个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。
复制和在你的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
运德Cirkel的回答有正确的想法。 它可以更加简化(避免使用的cat
):
exec 5>&1
FF=$(echo aaa|tee /dev/fd/5)
echo $FF
这里有一个例子都捕捉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
将被捕获。
您可以使用三个以上的文件描述符。 试一下:
http://tldp.org/LDP/abs/html/io-redirection.html
“每个打开的文件被分配的文件描述符。[2]标准输入,stdout和stderr文件描述符是0,1,和2中。为了打开其他文件,仍然存在描述符3-9有时有用分配这些额外的文件描述符的一个标准输入,标准输出,或标准错误作为临时复制链接“。
问题的关键是,它是否值得,使脚本更复杂正好可以达到这种效果。 其实这不是真的错了,你的方式做到这一点。
如果“控制台”你的意思是你目前的TTY,尝试
variable=$(command with options | tee /dev/tty)
这是稍有可疑的做法,因为人谁尝试使用这有时是当输出焊盘的地方意外时,他们没有一个TTY(cron作业等)感到惊讶。
替代使用/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