我遇到一个问题,让bash完全按我的意愿行事,这不是一个主要问题,但很烦人。
1。)我有一个运行的第三方软件,它产生一些输出作为stderr。其中一些是有用的,有些是经常我不关心的东西,我不想把它倾倒到屏幕上,但是我确实希望将stderr的有用部分转移到屏幕上。我认为实现这一目标的最佳方法是将stderr传递给函数,然后使用该函数中的条件来显示stderr。
2。)这很好用。但是我实现的解决方案在正确的时间丢弃了我的错误,但是然后返回一个bash提示符,我想在函数结束时总结错误的状态,但是echo-ing在这里打印出提示后的文本含义我必须按回车才能回到干净的提示。下面的例子将会清楚。
我的错误流生成器:
./ TestErrorStream.sh
#!/bin/bash
echo "test1" >&2
我的处理这个功能:
./ Function.sh
#!/bin/bash
function ProcessErrors()
{
while read data;
do
echo Line was:"$data"
done
sleep 5 # This is used simply to simulate the processing work I'm doing on the errors.
echo "Completed"
}
我获取Function.sh文件以使ProcessErrors()可用,然后运行:
2> >(ProcessErrors) ./TestErrorStream.sh
我希望(并希望)得到:
user@user-desktop:~/path$ 2> >(ProcessErrors) ./TestErrorStream.sh
Line was:test1
Completed
user@user-desktop:~/path$
但我真正得到的是:
user@user-desktop:~/path$ 2> >(ProcessErrors) ./TestErrorStream.sh
Line was:test1
user@user-desktop:~/path$ Completed
没有干净的提示。当然有提示,但是"已完成"正在打印提示后,我想打印之前,然后一个干净的提示出现。
注意:这是一个最低限度的工作示例,并且是人为的。虽然欢迎我的错误流问题的其他解决方案,但我也想了解如何使bash以我想要的方式运行此脚本。
感谢您的帮助
乔伊
答案 0 :(得分:0)
你的问题是while循环保持坚持stdin直到程序退出。 stdin的发布发生在" TestErrorStream.sh"的末尾,因此与函数中剩余的处理相比,您的提示几乎立即可用。
我建议你将命令包装在一个脚本中,这样你就可以在提示返回之前处理你想要的时间(我建议比函数处理其余行所需的时间长1秒)码)
我成功完成了这样做:
./ Functions.sh
#!/bin/bash
function ProcessErrors()
{
while read data;
do
echo Line was:"$data"
done
sleep 5 # simulate required time to process end of function (after TestErrorStream.sh is over and stdin is released)
echo "Completed"
}
./ TestErrorStream.sh
#!/bin/bash
echo "first"
echo "firsterr" >&2
sleep 20 # any number here
./ WrapTestErrorStream.sh
#!/bin/bash
source ./Functions.sh
2> >(ProcessErrors) ./TestErrorStream.sh
sleep 6 # <= this one is important
通过上述内容,您将获得一个很好的&#34;已完成&#34;处理26秒后,之前提示。 (无论是否有额外的&#34;时间&#34;命令都可以正常工作
user@host:~/path$ time ./WrapTestErrorStream.sh
first
Line was:firsterr
Completed
real 0m26.014s
user 0m0.000s
sys 0m0.000s
user@host:~/path$
注意:流程替换&#34;&gt;(ProcessErrors)&#34;是脚本的一个子进程&#34; ./ TestErrorStream.sh&#34;。因此,当脚本结束时,子进程不再与它绑定,也不与包装器绑定。这就是为什么我们需要最终的&#34;睡眠6&#34;
答案 1 :(得分:0)
#!/bin/bash
function ProcessErrors {
while read data; do
echo Line was:"$data"
done
sleep 5
echo "Completed"
}
# Open subprocess
exec 60> >(ProcessErrors)
P=$!
# Do the work
2>&60 ./TestErrorStream.sh
# Close connection or else subprocess would keep on reading
exec 60>&-
# Wait for process to exit (wait "$P" doesn't work). There are many ways
# to do this too like checking `/proc`. I prefer the `kill` method as
# it's more explicit. We'd never know if /proc updates itself quickly
# among all systems. And using an external tool is also a big NO.
while kill -s 0 "$P" &>/dev/null; do
sleep 1s
done
偏离主题侧面注意:我很想看看有多么糟糕的bash退伍军人/作者试图拥有这个。或者也许他们已经从看到this回来了。