我有一个像这样的 bash 函数:
run_mongo(){
mongo foo bar baz 2>&1 # send stderr to stdout
}
不幸的是,如果出现错误,这个 mongo 命令不会以 1 退出,所以我必须在 stdout/stderr 上进行匹配
如果有第一个匹配,是否有某种方法可以使用 grep 以 code > 0 退出?像这样的东西:
run_mongo | grep -e "if stdout/stderr matches this we exit with 1"
我认为执行此操作的方法如下:
run_mongo | grep -e "if stdout/stderr matches" | killer
其中 Killer 是一个一旦获得第一个标准输入就终止的程序。
答案1
是的,你可以用grep -vz
它来告诉grep
你找到与你给它的模式不匹配的行(-v
)并立即读取整个输入(z
),这样一个匹配就意味着整个事情失败:
$ printf 'foo\nbar\n' | grep -zqv foo && echo no || echo yes
yes
$ printf 'foo\nbar\n' | grep -zq foo && echo no || echo yes
no
所以,就你的情况而言,类似:
run_mongo(){
mongo foo bar baz 2>&1 | grep -vzq "whatever means failure"
}
if run_mongo; then
echo "Worked!"
else
echo "Failed!"
fi
如果您想避免读取整个输出,只需使用其他工具即可。以 Perl 为例:
mongo foo bar baz 2>&1 | perl -ne 'exit 1 if /whatever means failure/'
答案2
如果您需要尽快终止:
run_mongo () {
! mongo foo bar baz 2>&1 | grep -q 'bad-pattern'
}
如果在输出中找到该模式,这将mongo
尽快运行并终止该函数。bad-pattern
当模式匹配时,grep
立即退出,并mongo
在尝试写入死管道时立即接收 PIPE 信号。
由于!
,管道的退出状态将被反转,即,如果未找到模式,则退出状态为零;如果找到,则退出状态为非零。
如果您需要让其mongo
完成写入输出:
run_mongo () {
! mongo foo bar baz 2>&1 | grep 'bad-pattern' > /dev/null
}
这与此答案中的第一段代码相同,但grep
现在消耗mongo
.
答案3
@terdon 的解决方案看起来不错,因为我是 Node.js 的粉丝,我只是写了一个这样的程序:
#!/usr/bin/env node
process.stdin.resume().once('data', function () {
process.exit(1);
});
然后在我的 bash 脚本中有:
run_mongo(){
mongo foo bar baz 2>&1
}
exit_if_match(){
grep "$1" | "./node_modules/.bin/imminent_suicide"
}
run_mongo "foo" "bar" | exit_if_match "errmsg"
答案4
echo 'if stdout/stderr matches this' |
awk '$0 ~ "if stdout/stderr matches this" { exit 1; }' ; echo $?