我可以输出“curl”响应,同时检查是否存在错误字符串吗?

我可以输出“curl”响应,同时检查是否存在错误字符串吗?

我有一个正在运行的命令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退出grepgrep -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/filemktemp是正确的工具,但它不是由 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 中)独立检测ERRORWARNING输出。

  • 某些程序会根据 stdout 是终端、管道还是常规文件来改变其行为(请参阅如何欺骗命令,让其认为其输出将发送到终端)。我们的函数内部使用管道,因此在某些情况下,的输出failon foo program将与直接调用的输出不同program

答案2

我不知道你到底想实现什么,但我想你需要tee重定向错误输出curl -s whatever 2>&1|tee output.txt|grep ERROR

因此,您在文件 output.txt 中既有错误的 grep,也有 curl 命令的内容。

相关内容