在Linux shell中的程序同时过滤输出并获取退出代码

时间:2014-01-14 09:41:23

标签: java linux bash shell jenkins

我正在Jenkins中运行一个作业(Jenkins是一个开源的持续集成工具),它通过执行shell命令列表。其中一个命令是运行一个Java程序,它执行一些数据验证。如果遇到无效日期,Java程序将以非零退出代码退出,以便Jenkins可以发现这次构建失败。

不幸的是,Java程序向stdout和stderr打印了太多日志,其中只有少数是有用的。由于无法修改Java程序,我决定使用 grep 过滤输出。所以我把shell写成:

java -cp $CLASSPATH MetaValidatorMain | grep -v "useless keyword1"| grep -v "useless keyword2"

但问题是,在执行shell行之后,父进程(Jenkins)获得 grep 的退出代码 java ,以便Jenkins无法确定构建是否成功。

我也试过这个:

(java -cp $CLASSPATH MetaValidatorMain || exit 1) | grep -v "useless keyword1"| grep -v "useless keyword2"

也没用。

有人能告诉我怎样才能编写shell行来过滤输出并获得正确的退出代码。

THX

2 个答案:

答案 0 :(得分:2)

有点长,但你可以将程序输出重定向到一个文件,捕获返回,然后grep输出文件以获得你想要的内容:

java -cp $CLASSPATH MetaValidatorMain > /tmp/outfile.txt 2>&1
RETURN_CODE=$?
grep -v "useless keyword1" /tmp/outfile | grep -v "useless keyword2"
exit RETURN_CODE

答案 1 :(得分:1)

有3种方法可以做到这一点。但是,您当前的设置应该有效。这里的原因是如果命令失败,grep将无法匹配任何内容,因此grep将以状态1返回(除非程序始终显示该文本,无论如何)。

Pipefail

第一种方法是设置pipefail选项。这是最简单的,它的作用基本上是将退出状态$?设置为最后一个程序的退出代码以退出非零(如果所有退出成功则为零)。

# false | true; echo $?
0
# set -o pipefail
# false | true; echo $?
1

$ PIPESTATUS

Bash还有一个名为$PIPESTATUS的变量,它包含最后一个命令中所有程序的退出状态。

# true | true; echo "${PIPESTATUS[@]}"
0 0
# false | true; echo "${PIPESTATUS[@]}"
1 0
# false | true; echo "${PIPESTATUS[0]}"
1
# true | false; echo "${PIPESTATUS[@]}"
0 1

您可以使用第3个命令示例来获取所需的管道中的特定值。

此解决方案可能无法使用。我认为$PIPESTATUS可能已添加到最新版本的bash中,而您的操作系统可能没有。

单独执行

这是解决方案中最笨拙的问题。分别运行每个命令并捕获状态

# java -cp $CLASSPATH MetaValidatorMain > /tmp/outfile.txt 2>&1
# RETURN_CODE=$?
# grep -v "useless keyword1" /tmp/outfile | grep -v "useless keyword2"
# exit RETURN_CODE