在自动化中使用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,它可以根据所存在的东西来包装curl 或wget 。