我正在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
答案 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
选项。这是最简单的,它的作用基本上是将退出状态$?
设置为最后一个程序的退出代码以退出非零(如果所有退出成功则为零)。
# false | true; echo $?
0
# set -o pipefail
# false | true; echo $?
1
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