获取管道后台进程的退出代码

时间:2016-05-16 15:33:03

标签: bash pipe background-process exit-code

someCommand 2>&1 | grep pattern &

如何获取someCommand的退出状态?

PIPESTATUS不起作用,因为它是后台进程。

我发现了这个link,它似乎有效但只有当我使用它时才这样。简单echo屏幕似乎不起作用。我想知道是否可以在不创建临时文件的情况下获取退出代码。

2 个答案:

答案 0 :(得分:3)

在bash中你可以做到:

echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"

示例:

$ ls -l | grep somefile
-rw-rw-r--  1 me me     32 May  4 15:47 somefile
$ echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
0 0

$ ls -l 1>/dev/null | grep while
$ echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
0 1

对于管道前景进程

如果脚本说的testscript.sh包含:

#!/bin/bash
echo "Some Stuff"
exit 29 # Some random exit code for testing

DO

$./testscript.sh | grep somestuff
$ echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
29 1

对于管道后台进程

方法1:使用pipefail

对于包含以下内容的testscript.sh:

#!/bin/bash
set -eo pipefail  
#set -o pipefail causes a pipeline to produce a failure return code
#If a command fails, set -e will make the whole script exit,
cat nonexistingfile # this command fails
echo "Some Stuff"
exit 29

$ ./testscript.sh 2>/dev/null | grep Some &
[2] 7684
$ fg 2
bash: fg: job has terminated
[2]-  Exit 1         ./testscript.sh 2> /dev/null | grep --color=auto Some

您将获得退出状态1,从中您可以得出脚本失败的结论。

如果cat nonexistingfile已删除,您将获得:

[2]-  Done                    ./37257668.sh 2> /dev/null | grep --color=auto Some

Disdvantage :pipefail将为所有退出代码返回一个不是特定于失败命令的退出代码

方法2:来源shell脚本

$ . ./testscript.sh 2>/dev/null | grep Some & #mind the dot in the beginning
$ echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
29 0

最后触摸

如果您怀疑shell脚本中的单个命令失败,那么测试脚本可以在下面执行:

#no shebang
echo "Some Stuff"
ls non_existent 2>/dev/null || ls__return_value=50 

$. ./testscript | grep "Some"

$if [ $ls__return_value -eq 50 ]; then echo "Error in ls"; fi

答案 1 :(得分:1)

使用临时文件

您可以将保存PIPESTATUS内容的代码放在{ ... }内的临时文件中,然后在后台运行。如果我们对管道中多个命令的退出代码感兴趣,则需要这种方法:

{ 
  someCommand 2>&1 | grep -- pattern
  printf "0=%s\n1=%s\n" "${PIPESTATUS[0]}" "${PIPESTATUS[1]}" > status.out
} &
wait "$!"
# grab the exit code from status.out file

没有临时文件

{ 
  someCommand 2>&1 | grep -- pattern
  exit ${PIPESTATUS[0]}
} &
wait "$!"
echo $?   # this is the exit code of someCommand
  

等待:等待[n]

Wait for the specified process and report its termination status.  If
N is not given, all currently active child processes are waited for,
and the return code is zero.  N may be a process ID or a job
specification; if a job spec is given, all processes in the job's
pipeline are waited for.