在自动化中使用curl

364 阅读4分钟

在自动化中使用curl

了解如何优化curl,以便在批处理脚本、供应系统和持续部署管道中下载网络资源

Nick Galbreath-四月 25, 2018

很多时候,在配置系统、批处理脚本和CI/CD管道中,需要一些调用来获取外部(网络)资源。虽然最好是尽可能地消除外部依赖和网络调用,但有时也是没办法的事。在这种情况下,无处不在的curl就很有用。然而,在默认情况下,curl并没有为自动化进行很好的优化。特别是。

  • 显示了一个为人类设计的进度表。在CI/CD日志中,进度表没有增加任何价值,而且是可怕的日志输出。
  • 不跟随重定向。你几乎总是想跟随重定向。
  • 不超时。缺少超时可能(而且确实)导致CI/CD运行挂起。我见过Jenkins和Travis-ci的运行由于下载挂起而花费数小时。
  • 在404时不会失败(或非零退出)。只要curl收到了服务器发回的信息,就是成功的,HTTP代码并不重要。这可能不是你对成功的定义。
  • 在瞬时错误时不重试。对人类来说完全没问题。对CI/CD运行来说,完全是坏事。

这并不奇怪。Curl已经被研究了几十个年头,并且有机地成长。它有许多通常不显眼的标志来控制它的行为。

重要的标志

下面是在批处理脚本中使用的最重要的标志。

关掉进度条

-s--silent 标志可以关闭所有的输出。不幸的是,这也意味着错误输出,而这可能是我们想要的。所以...

开启错误输出

-S--show-errors 标志会重新开启错误输出。你可能想要这个。

在404时失败

标志-f--fail 导致 curl 在没有得到 HTTP 状态 200 的情况下退出(或失败),退出代码为 22。前面的标志--show-errors 是需要的,以便真正看到状态代码是什么。请看下面的方法,以获得状态代码并更优雅地退出。

跟踪重定向

-L--location 标志指示 curl 跟踪重定向,这可能是人们想要的。使用--max-redirs 标志可以防止服务器配置错误造成的无限循环。

超时

在shell脚本中,有许多超时的方法,但curl自动提供了一个。-m--max-time 标志将指定一个超时时间,单位是秒。超时后,连接被取消,curl返回一个非零的退出代码。

重试

与超时类似,有很多方法可以在瞬时失败时重试一个命令。同样,curl提供了一个内置的机制。

--retry NUM   Retry request NUM times if transient problems occur
--retry-connrefused  Retry on connection refused (use with --retry)
--retry-delay SECONDS  Wait SECONDS between retries
--retry-max-time SECONDS  Retry only within this period

一个好的起点可能是。

--retry 3 --retry-connrefused --retry-delay 2

所有的一起

curl --silent --show-error \
  -L --max-redirs 3 \
  --retry 3 --retry-connrefused --retry-delay 2 \
  --max-time 30

对于快速和肮脏的脚本,你可以用以下方法作弊。

curl -sfSL

404时更好的失败

Curl有一种使用-w 标志来定制输出的方法。我们可以用这个方法来处理HTTP状态的失败。

http_code=$(curl -w '%{http_code}' -s -o dest src)
if [ "$http_code" != "200" ]; then
    echo "curl received HTTP status $http_code"
    exit 1
fi

安全性

不要使用-k--insecure 标志。这将关闭关键的安全检查。如果你认为你需要使用这个,请花时间进行调试和正确修复。这并不是什么抽象的问题。真正的网站已经因为关闭这些安全检查而被攻击了。

最后说明

最好的解决办法通常是消除脚本中的网络调用,要么找到不同的方法,要么检查已知的良好版本的资源。但是当这不可能时(或者当它真的不重要时),这些curl标志会更优雅地处理错误。

如果你需要下载多个项目,通过并行下载可以节省时间。详见使用Xargs并行化Shell或Bash脚本

如果你想从一个未知的操作系统中启动一些东西,那么可以看看一个posix shell抽象shlib,它可以根据所存在的东西来包装curlwget