2011-09-28 70 views
6

我想转以下几点:bash进程替换和退出代码

git status --short && (git status --short | xargs -Istr test -z str)

这让我镜像输出到标准输出和对结果做一个零长度检查到的东西的期望的结果接近:

git status --short | tee >(xargs -Istr test -z str)

不幸返回三通管的退出代码(总是零)。

有什么办法可以优雅地获得替代过程的退出代码吗?

[编辑]

我与现在的下面,它可以防止运行相同的命令两次会,但似乎乞求更好的东西:

OUT=$(git status --short) && echo "${OUT}" && test -z "${OUT}"

+0

对不起,你究竟想要达到什么目的?只需检查该目录中是否有git状态? –

+0

是的,它是部署脚本的一部分,如果目录很脏,应该退出非零值。 – jodell

回答

5

看看这里:

 
    $ echo xxx | tee >(xargs test -n); echo $? 
xxx 
0 
    $ echo xxx | tee >(xargs test -z); echo $? 
xxx 
0 

看这里:

 
    $echo xxx | tee >(xargs test -z; echo "${PIPESTATUS[*]}") 
xxx 
123 
    $echo xxx | tee >(xargs test -n; echo "${PIPESTATUS[*]}") 
xxx 
0 

那是?

又见Pipe status after command substitution

+0

我不知道PIPESTATUS,这很有帮助,谢谢。 – jodell

+4

如果有其他人出现,并认为PIPESTATUS解决了这个问题,它不会。如果echo $?被移动到>(...)构造内,它也表现得如预期。如果将PIPESTATUS版本移出外部,则在两种情况下都会返回0。 –

0
#!/bin/bash 
if read q < <(git status -s) 
then 
    echo $q 
    exit 
fi 
2

我一直工作在这一段时间,似乎是没有办法做到这一点与过程替代,除了诉诸内嵌信号,并能真的只能用于输入管道,所以我不打算扩展它。

但是,bash-4.0提供了coprocesses,它可以用来取代在这种情况下的进程替换,并提供清晰的收获。

你提供下面的代码片段:

git status --short | tee >(xargs -Istr test -z str) 

可以通过东西都被替换为:

coproc GIT_XARGS { xargs -Istr test -z str; } 
{ git status --short | tee; } >&${GIT_XARGS[1]} 
exec {GIT_XARGS[1]}>&- 
wait ${GIT_XARGS_PID} 

现在,对于一些解释:

coproc调用创建一个新的协进程,命名它GIT_XARGS(你可以使用任何你喜欢的名字),并运行大括号中的命令。为协处理创建了一对管道,重定向其标准输入和标准输出。

coproc调用设置两个变量:

  1. ${GIT_XARGS[@]}含有管道处理stdin和stdout,适当地([0]从标准输出读,[1]写入标准输入),
  2. ${GIT_XARGS_PID}含有协进程PID。

然后,运行命令并将其输出定向到第二个管道(即coprocess的stdin)。看似隐秘的>&${GIT_XARGS[1]}部分扩展到>&60这是常规的输出到fd重定向。

请注意,我需要把你的命令放在大括号中。这是因为管道会导致子进程生成,并且它们不会从父进程继承文件描述符。换句话说,执行以下操作:

git status --short | tee >&${GIT_XARGS[1]} 

会失败,无效的文件描述符错误,因为相关的FD的父进程存在,而不是催生tee过程。将其放在大括号中会导致bash将重定向应用于整个管道。

exec调用用于关闭到您的协处理的管道。在使用进程替换时,该进程会作为输出重定向的一部分生成,并且在重定向不再生效后立即关闭该进程的管道。由于协处理管道的生命周期超出了单个重定向,我们需要明确地关闭它。

关闭输出管道应该会导致进程在标准输入上获得EOF条件并正常终止。我们使用wait等待终止并收获。 wait返回协处理器的退出状态。

作为最后一个注意事项,请注意,在这种情况下,您不能使用kill来终止协处理,因为这会改变其退出状态。

+0

tee在这里其实没什么用处,stdout net会重定向到stdout。 – weynhamz

+0

'exec {GIT_XARGS [1]}>& - 'returns' -bash:exec:{GIT_XARGS [1]}:找不到我的。 –

+0

你有bash-4.0或更新版本吗? –