我的问题很简单 -当curl执行多个请求时,有没有办法显示每个URL的curl的单独退出状态?
让我们假设我需要检查站点a.com、b.com并c.com查看它们:
000,我需要显示curl的exit code。注意 - a.com、b.com、c.com在此代码/问题中用作示例。在真实的脚本中,我确实有一个有效的 URL 列表 - 其中超过 400 个具有非重叠模式 - 并且它们返回各种 HTTP 代码 - 200/4xx/5xx 以及 000。
000 是curl 无法建立连接的情况,但提供退出代码以了解阻止其建立连接的原因。就我而言,还有许多退出代码 - 6、7、35、60。
我尝试运行以下代码
unset a
unset rep
a=($(curl -s --location -o /dev/null -w "%{response_code}\n" {https://a.com,https://b.com,https://a.com}))
rep+=("$?")
printf '%s\n' "${a[@]}"
echo
printf '%s\n' "${rep[@]}"
Run Code Online (Sandbox Code Playgroud)
虽然上述代码返回每个单独请求的 HTTP 返回代码,但仅显示最后一个请求的退出代码。
000
000
000
60
Run Code Online (Sandbox Code Playgroud)
当我提供多个 URL 进行卷曲时,我确实需要能够记录单独的退出代码。这个问题有解决方法/解决方案吗?
一些附加信息:目前,我将所有 URL 放入一个数组中,并通过它运行一个循环,分别检查每个 URL。然而,浏览 400 个 URL 需要 1-2 小时,我需要以某种方式加快该过程。我确实尝试将-Z 与curl 一起使用。虽然它确实使进程加快了约 40-50%,但没有帮助,因为除了仅显示上述最后的退出状态之外,在本例中,退出状态始终显示为 0,这是不正确的。
PS 我愿意使用任何其他命令行工具,如果它可以解决上述问题 - 并行检查 10s/100s 的 URL 并记录其 HTTP 代码,如果无法建立连接 - 记录其他信息,例如curl的 Exit代码可以。
谢谢。
退出代码被命名为“退出代码”,因为它是在命令退出时返回的。如果你只运行一个,curl那么它只会退出一次。
curlcurl当给定一个或多个 URL 时,可能会提供一种检索代码的方法,该代码相当于单独处理当前 URL的退出代码;它将与%{response_code}您使用的类似。不幸的是,似乎没有这样的功能(但是;也许添加它)。要获得 N 个退出代码,您需要 N 个curl进程。你需要运行这样的N次:
curl \xe2\x80\xa6 ; echo "$?"\nRun Code Online (Sandbox Code Playgroud)\n我知道你的 N 大约是 400,你循环尝试了这个,花了几个小时。好吧,生成 400curl秒(echo如果不是内置的,即使是 400 秒echo;如果需要的话,即使是 400 个(子)炮弹)也不是那么耗时。罪魁祸首是你同步运行所有这些运行所有这些(不是吗?)。
可以异步循环和运行代码片段:
\nfor url in \xe2\x80\xa6 ; do\n ( curl \xe2\x80\xa6 ; echo "$?" ) &\ndone\nRun Code Online (Sandbox Code Playgroud)\n但这种简单的方法存在几个问题:
\ncurl,没有队列。就性能和可用资源而言,这可能非常糟糕。curl来自两个或多个命令(例如,来自两个或多个命令)的并发输出可能会交错,可能是在中线。curl或者echo来自另一个子 shell 的输出可能会在curl其相应的echo.parallel正确的工具是parallel. 该工具的基本变体(来自moreutils,至少在 Debian 中)解决了 (1)。在某些情况下它可能解决(2)。无论如何,这都是无关紧要的,因为这个变体不能解决(3)或(4)。
GNUparallel解决了所有这些问题。
它通过设计解决了(1)。
\n它用它的--group选项解决了(2)和(3):
\n\n\n
--group
\n分组输出。每个作业的输出都分组在一起,并且仅在命令完成时才打印。首先是 Stdout(标准输出),然后是 stderr(标准错误)。[\xe2\x80\xa6]
(来源)
\n这是默认值,因此通常您不必显式使用它。
\n它用它的选项解决了(4)--keep-order:
\n\n\n
--keep-order
\n-k
\n保持输出顺序与输入顺序相同。通常,作业完成后就会立即打印作业的输出。[\xe2\x80\xa6]-k仅影响打印输出的顺序,而不影响作业运行的顺序。
(来源)
\n在 Debian 中,GNUparallel位于名为parallel. 这个答案的其余部分使用 GNU parallel。
<urls parallel -j 40 -k \'curl -s --location -o /dev/null -w "%{response_code}\\n" {}; echo "$?"\'\nRun Code Online (Sandbox Code Playgroud)\n其中urls是带有 URL 的文件,-j 40意味着我们最多允许 40 个并行作业(根据您的需求和能力进行调整)。{}在这种情况下,嵌入shell 代码是安全的。这是这个答案中明确提到的一个例外:永远不要嵌入{}shell 代码!
输出会像
\n404\n0\n200\n0\n000\n7\n\xe2\x80\xa6\nRun Code Online (Sandbox Code Playgroud)\n请注意,单引号字符串是 shell 代码。您可以在其中实现一些逻辑,因此0永远不会打印退出代码。如果我是你,我无论如何都会在同一行的开头位置打印它:
<urls parallel -j 40 -k \'\n out="$(\n curl -s --location -o /dev/null -w "%{response_code}" {}\n )"\n printf "%s %s\\n" "$?" "$out"\'\nRun Code Online (Sandbox Code Playgroud)\n现在即使有一些curl在打印之前被手动终止,您也会在第一列中得到一些内容。这对于解析很有用(我们将返回它)。例子:
0 404\n0 200\n7 000\n\xe2\x80\xa6\n143 \n\xe2\x80\xa6\nRun Code Online (Sandbox Code Playgroud)\n其中143意味着curl被终止(请参阅进程终止时的默认退出代码)。
如果您的 URL 位于名为 的数组中urls,请避免使用以下语法:
parallel \xe2\x80\xa6 ::: "${urls[@]}" # don\'t\nRun Code Online (Sandbox Code Playgroud)\nparallel是一个外部命令。如果数组足够大,那么您将命中argument list too long。使用这个代替:
printf \'%s\\n\' "${urls[@]}" | parallel \xe2\x80\xa6\nRun Code Online (Sandbox Code Playgroud)\n它会起作用,因为在 Bash 中printf是内置的,因此之前的所有内容|都由 Bash 内部处理。
要从urls数组到a数组rep,请按以下步骤操作:
unset a\nunset rep\nwhile read -r repx ax; do\n rep+=("$repx")\n a+=("$ax")\ndone < <(printf \'%s\\n\' "${urls[@]}" \\\n | parallel -j 40 -k \'\n out="$(\n curl -s --location -o /dev/null -w "%{response_code}" {}\n )"\n printf "%s %s\\n" "$?" "$out"\')\nprintf \'%s\\n\' "${a[@]}"\necho\nprintf \'%s\\n\' "${rep[@]}"\nRun Code Online (Sandbox Code Playgroud)\n如果我们在第二列中生成退出代码(这更容易,您不需要像这样的辅助变量out)并相应地调整我们的read,所以它是read -r ax repx,那么一行<empty ax><space>143将保存143到,ax因为read忽略前导空格(it\'很复杂)。通过颠倒顺序,我们可以避免代码中出现错误。像这样的行143<space><empty ax>由 正确处理read -r repx ax。
您有望在几分钟内检查 400 个 URL。持续时间取决于您允许并行运行的作业数量 ( parallel -j \xe2\x80\xa6),还取决于:
curl下载数据量和速度;--connect-timeout和等选项--max-time(考虑使用它们)。| 归档时间: |
|
| 查看次数: |
2790 次 |
| 最近记录: |