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

Java 在Linux shell中过滤输出并同时获取程序的退出代码,java,linux,bash,shell,jenkins,Java,Linux,Bash,Shell,Jenkins,我在Jenkins中运行一个作业(Jenkins是一个开源的持续集成工具),通过执行一系列shell命令。其中一个命令是运行一个Java程序,该程序执行一些数据验证。如果遇到无效日期,Java程序将以非零退出代码退出,这样Jenkins可以发现这次构建失败 不幸的是,Java程序向stdout和stderr输出了太多的日志,其中只有少数有用。由于Java程序无法修改,我决定用grep过滤输出。所以我把shell写成: java -cp $CLASSPATH MetaValidatorMain |

我在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)获得了java的grep indead的退出代码,因此Jenkins无法确定构建是否成功

我也试过:

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

谁能告诉我如何编写shell行来过滤输出,同时获得正确的退出代码


thx有点长,但您可以将程序输出重定向到一个文件,捕获返回值,然后根据需要的内容对输出文件进行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

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

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

$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
您可以使用第三个命令示例在管道中获取所需的特定值

但此解决方案可能不可用。我认为,
$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

确实有点长的路要走,但是如果行得通,代码也很清楚。谢谢
# java -cp $CLASSPATH MetaValidatorMain > /tmp/outfile.txt 2>&1
# RETURN_CODE=$?
# grep -v "useless keyword1" /tmp/outfile | grep -v "useless keyword2"
# exit RETURN_CODE