Curl 命令中的 Bash 脚本多线程

Curl 命令中的 Bash 脚本多线程

这是一个 shell 脚本,它使用域及其参数来查找状态代码。由于线程的原因,它运行得更快,但会错过很多请求。

while IFS= read -r url <&3; do
    while IFS= read -r uri <&4; do
    urlstatus=$(curl -o /dev/null --insecure --silent --head --write-out  '%{http_code}' "${url}""${uri}" --max-time 5 ) &&
    echo "$url  $urlstatus $uri" >> urlstatus.txt &
done 4<uri.txt 
done 3<url.txt

如果我正常运行,它会处理所有请求,但速度非常低。有没有一种方法可以保持速度并且不会错过所有请求。

答案1

您遇到并行附加到文件的问题。简单的答案是:不要。

以下是使用 GNU Parallel 的方法:

doit() {
    url="$1"
    uri="$2"
    urlstatus=$(curl -o /dev/null --insecure --silent --head --write-out  '%{http_code}' "${url}""${uri}" --max-time 5 ) &&
    echo "$url  $urlstatus $uri"
}
export -f doit

parallel -j200 doit :::: url uri >> urlstatus.txt

GNU Parallel 默认对输出进行序列化,因此您不会从一个作业中获得与另一作业的输出混合的输出。

GNU Parallel 可以使用 轻松地将输入包含在输出中--tag。因此,除非输出格式是固定的,否则我会这样做:

parallel --tag -j200 curl -o /dev/null --insecure --silent --head --write-out  '%{http_code}' {1}{2} --max-time 5 :::: url uri >> urlstatus.txt

它将给出相同的输出 - 只是格式不同。代替:

url  urlstatus uri

你得到:

url uri urlstatus

答案2

虽然您可以运行多个流程在 shell 中异步(利用“ shellcmd &”语法),子进程可以(并且经常)在下一个命令捕获其输出之前结束。而且,正如 @Ole-Tange 指出的那样,无法确保以正确的顺序将该输出写入文件!

许多人希望使用不同的脚本语言来管理多个线程,而不是使用 shell 脚本......

答案3

要并行执行多个curl传输,我们需要考虑另一个工具:xargs。

如果您不熟悉 xargs,它是一个非常强大的 Linux 实用程序。有了它,我们可以以很少的开销并行执行多个(动态)curl 命令。例子:

seq 1 3 | xargs -n1 -P3 bash -c 'i=$0; url="http://mytestserver.net/10m_test.html?run=${i}"; curl -O -s $url'

此代码将并行运行 3 个curl 命令。 -P 参数允许您设置所需的并行执行数量。在此示例中,我们使用 seq 命令将数字参数传递给我们的命令,以便每个 URL 都具有唯一的运行编号。 -n 参数只是限制每次执行传递的参数数量。 -c 参数是我们指定要运行的命令的地方。

请注意,此示例不提供任何输出,它只是运行传输。如果你想保存输出,你可以使用前面关于输出格式的讨论来决定你想要输出什么以及如何保存它。

从这里,您可以扩展迭代次数,传递其他有趣的参数(可能是文件中的 URL 列表),等等。我们在生成后台流量时经常使用此类命令来模拟特定的网络条件。

相关内容