【发布时间】:2011-06-25 12:19:15
【问题描述】:
我通过 sed 管道输出一个长期运行的构建过程的输出以进行语法高亮,实现为“mvn”的包装器。
此外,我还有一个“监控”脚本,当构建完成时,它会在桌面上通知我。监控脚本检查其参数的退出状态并报告“成功”或“失败”。
通过 sed 管道化 maven 输出,退出状态始终为“ok”,即使构建失败。
我怎样才能通过 sed 传递正确的退出状态?
还有其他选择吗?
【问题讨论】:
我通过 sed 管道输出一个长期运行的构建过程的输出以进行语法高亮,实现为“mvn”的包装器。
此外,我还有一个“监控”脚本,当构建完成时,它会在桌面上通知我。监控脚本检查其参数的退出状态并报告“成功”或“失败”。
通过 sed 管道化 maven 输出,退出状态始终为“ok”,即使构建失败。
我怎样才能通过 sed 传递正确的退出状态?
还有其他选择吗?
【问题讨论】:
也许PIPESTATUS 变量可以提供帮助。
【讨论】:
bash -e 'mvn blah | sed -e SomeHighlightRegEx; exit ${PIPESTATUS[0]}'
如果您使用的是 Bash,则可以选择使用 set -o pipefail 选项,但由于它依赖于 bash,因此它不可移植,并且无法在 crontab 上工作,除非您将整个内容包装在 bash 中env(不好的解决方案)。
http://bclary.com/blog/2006/07/20/pipefail-testing-pipeline-exit-codes/
【讨论】:
这是众所周知的背部疼痛。如果您正在使用 bash(可能还有许多其他现代 sh 变体),您可以访问 PIPESTATUS 数组以获取管道中较早的程序的返回值。 (通常,管道的返回值是管道中最后一个程序的返回值。)如果您使用的外壳没有 PIPESTATUS(或者如果您想要可移植性),您可以执行以下操作: #!/bin/sh # 运行 'echo foo |假 | sed s/f/t/',记录状态 # RV 中的错误数 eval $( { { echo foo | false; printf RV=$? >&4; } | sed s/f/t/ >&3; 4>&1; ) 3>&1 回声 RV=$RV # 运行 'echo foo |猫 | sed s/f/t/',记录状态 # 房车里的猫 eval $( { { echo foo | cat; printf RV=$? >&4; } | sed s/f/t/ >&3; 4>&1; ) 3>&1 回声 RV=$RV
在每种情况下,RV 将分别包含 false 和 cat 的返回值。
【讨论】:
Bastil,因为管道不关心退出状态,你只能知道 sed 是否正常退出。如果找不到预期的文本,我会增强 sed 脚本(或者可能考虑使用 3 行 Perl 脚本)以失败状态退出,类似于伪代码:
read($stdin)
if blank
exit(1) // output was blank, or on $stderr
else
regular expression substitution here
end
// natural exit success here
您可以将其作为 perl 单行器来完成,同样可以在 sedscript 中完成(但据我所知,在 sed 单行器中不行)
【讨论】:
也许您可以使用命名管道?这是一个例子:
FIFODIR=`mktemp -d`
FIFO=$FIFODIR/fifo
mkfifo $FIFO
cat $FIFO & # An arbitrary pipeline
if false > $FIFO
then
echo "Build succeeded"
else
echo "Build failed" # This line WILL execute
fi
rm -r $FIFODIR
【讨论】:
一周后我得到了解决方案:
本来我想做的
monitor "mvn blah | sed -e SomeHighlightRegEx"
monitor 会对 sed(而不是 mvn)的退出状态做出反应。
这样做更容易
monitor "mvn blah" | sed -e SomeHiglightRegEx
请注意,这将通过 sed 管道输出监视器,而监视器脚本对 mvn 的状态作出反应。
无论如何感谢其他想法。
【讨论】: