我有一个正在运行的命令curl
。即使服务器响应在某处包含字符串 ERROR,curl 命令也始终能成功解析。
我是否可以通过某种 shell 脚本或函数(首选 zsh)以某种方式检测此响应,同时将输出通过管道传输到终端,并使整个命令变为假的?
答案1
请参阅第一部分我的另一个答案以及其中的链接。您想检测一个字符串。curl
根据 HTML 错误代码进行失败似乎更优雅。如果可以通过这种方式获得所需的结果,那么它就是正确的方法。
否则,请使用以下通用 shell 函数:
failon() (
pattern="$1"
shift
[ "$#" -eq 0 ] && set cat
FAILON_STATUS="${FAILON_STATUS:-125}"
set -o pipefail
{ "$@" \
| tee -p /proc/self/fd/3 \
| { grep -q -- "$pattern" && return "$FAILON_STATUS" || return 0; }
} 3>&1
)
用法:
failon [pattern [command [arg...]]]
command [arg...]
该函数的主要目的是,如果 的输出包含与 匹配的行,则返回非零退出状态pattern
。无论是否匹配,输出都会打印到函数的标准输出。
例子:
failon ERROR curl …
注释和说明:
以
pattern
原样提供给,因此它是一个正则表达式。只要有一行,grep
空或未定义将匹配任何行。pattern
该函数应该可以在 bash、zsh 和许多其他 shell 中工作。据我所知,我使用的 shell 语法是可移植的。不可移植的东西独立于 shell,除非
set -o pipefail
它属于 shell,并且不可移植。我的意思是还没有。它受到广泛支持,并将被添加到 POSIX 标准中。感谢
pipefail
,如果未找到模式并且tee
没有失败(通常它不会失败)那么该函数将返回指定命令的退出状态(例如curl
)。如果找到模式,则函数将返回
125
。我选择的125
原因如下:它不是预订的,
man 1 curl
在我的操作系统中已经指定了退出代码,96
并且将来可能会出现更多代码。
FAILON_STATUS
您可以通过环境变量根据需要调整此数字。例如FAILON_STATUS=120 failon …
。注意FAILON_STATUS=0
从技术上讲有效,但毫无用处。tee -p
不可移植。-p
tee
如果在退出前得到,Without 将退出。一旦找到模式,就会SIGPIPE
退出grep
。grep -q
即使退出前, Thank to-p
tee
也会将其整个输入转发到/proc/self/fd/3
(最终是函数的标准输出) 。grep
如果您
tee
不支持-p
,最直接的解决方法是使用grep -- "$pattern" >/dev/null
。现在grep
将默默处理所有数据,它不会提前退出。缺点是它会在首次找到模式后执行不必要的匹配行工作。/proc/self/fd/…
不可移植;希望你的操作系统支持它。即使不支持,也总有一种方法可以curl … | tee /temporary/file
在 之后! grep -q ERROR /temporary/file
获取虚假的退出状态ERROR
。这种方法非常简单,吻, 但:在您的一条评论中,您说您不想将输出保存到文件中;
一般来说,安全可靠地创建一个并不容易
/temporary/file
;mktemp
是正确的工具,但它不是由 POSIX 指定的。
在 zsh 中,您可以执行
"$@" >&3 | { grep -q …
(而不是"$@" | tee … | { grep -q …
),从而摆脱tee -p /proc/self/fd/3
任何潜在问题。--
解释如下:--
(双破折号)是什么意思?如果
command
未指定,则函数将使用cat
。这允许您将其用作failon
“过滤器”:curl … | failon ERROR
注意这种方式很容易丢失退出状态
curl
。另一方面,也可以这样做:curl … | failon ERROR | failon WARNING
并检查
PIPESTATUS
(在 bash 中)或pipestatus
(在 zsh 中)独立检测ERROR
并WARNING
输出。某些程序会根据 stdout 是终端、管道还是常规文件来改变其行为(请参阅如何欺骗命令,让其认为其输出将发送到终端)。我们的函数内部使用管道,因此在某些情况下,的输出
failon foo program
将与直接调用的输出不同program
。
答案2
我不知道你到底想实现什么,但我想你需要tee
重定向错误输出curl -s whatever 2>&1|tee output.txt|grep ERROR
因此,您在文件 output.txt 中既有错误的 grep,也有 curl 命令的内容。