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