正确执行具有交互式输入的bash命令

时间:2019-03-25 13:58:18

标签: bash

我尝试从bash执行命令并检索stdout,stderr和退出代码。 到目前为止,一切都很好。

问题开始于该程序具有交互式输入。

更确切地说,我执行“ git commit”(不带-m),并执行“ GNU nano”以放置提交消息。

如果我只是简单地使用:

git commit

exec git commit

我可以看到提示,但看不到stdout / stderr。

如果我使用

output=`git commit 2>&1`

output=$(git commit 2>&1)

我可以检索stdout / stderr,但是看不到提示。 我仍然可以按ctrl + X放弃git commit。

我的第一次尝试是通过函数调用,脚本最终挂在黑屏上,并且ctrl + x / ctrl + c不起作用。

function Execute()
{
    if [[ $# -eq 0 ]]; then
        echo "Error : function 'Execute' called without argument."
        exit 3
    fi


    local msg=$("$@ 2>&1")
    local error=$?
    if [[ $error -ne 0 ]]; then
        echo "Error : '"$(printf '%q ' "$@")"' return '$error' error code."
        echo "$1 message :"
        echo "$msg"
        echo
        exit 1
    fi
}

Execute git commit

我开始耗尽想法/知识。我想做的事是不可能的吗?还是有我不知道的方法?

1 个答案:

答案 0 :(得分:0)

尝试使用此方法,将每行输出处理到stdout或stderr并根据内容重定向:

#!/bin/env bash

foo() {
    printf 'prompt: whos on first?\n' >&2
    printf 'error: uh-oh\n' >&2
}

var=$(foo 2>&1 | awk '{print | "cat>&"(/prompt/ ? 2 : 1)}' )
echo "var=$var"

$ ./tst.sh
prompt: whos on first?
var=error: uh-oh

或仅处理stderr的代码:

#!/bin/env bash

foo() {
    printf 'prompt: whos on first?\n' >&2
    printf 'error: uh-oh\n' >&2
}

var=$(foo 2> >(awk '{print | "cat>&"(/prompt/ ? 2 : 1)}') )
echo "var=$var"

$ ./tst.sh
prompt: whos on first?
var=error: uh-oh

awk命令根据内容将其输入拆分为stderr或stdout,只有stdout保存在变量var中。我不知道您的提示会出现在stderr还是stdout上,或者您真的想去哪里,但是要进行按摩以适合您想要去stdout vs stderr的内容以及想要在变量vs中看到的内容,以及打印到屏幕。您只需要在提示中包含一些内容即可识别出来,这样就可以将提示与其他stdout和stderr分开,并在其他所有内容都重定向到stdout时将提示打印到stderr。

或者,这是一个将第一行(无论内容如何)打印到stderr进行显示,并将其他所有内容打印到stdout进行捕获的版本:

$ cat tst.sh
#!/bin/env bash

foo() {
    printf 'prompt: whos on first?\n' >&2
    printf 'error: uh-oh\n' >&2
}

var=$(foo 2>&1 | awk '{print | "cat>&"(NR>1 ? 1 : 2)}' )
echo "var=$var"

$ ./tst.sh
prompt: whos on first?
var=error: uh-oh