提示输出发生在提示之后,而不是之前,这意味着我必须手动按回车键

时间:2014-05-29 14:00:37

标签: linux bash echo prompt stderr

我遇到一个问题,让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以我想要的方式运行此脚本。

感谢您的帮助

乔伊

2 个答案:

答案 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回来了。