春江暮客

春江暮客的个人学习分享网站

curl 实战:网站部署后,检查状态码、跳转和页面内容

2026-09-20 技术
curl 实战:网站部署后,检查状态码、跳转和页面内容

文件已经上传成功,新页面就一定能被读者看到吗?实际发布时,仍可能遇到地址写错、缓存没有更新,或者服务器返回错误页面的情况。

完成 rsync 文件同步 后,可以用本文的 curl 流程检查公开访问结果:保存页面、核对状态码和正文,再写一个遇到异常就返回失败的检查脚本。

1. 检查本机工具

以下示例使用 macOS 或 Linux 终端,以及兼容 POSIX 的 shell:

curl --version
curl --help

如果 Debian 或 Ubuntu 上没有 curl,可以安装:

sudo apt update
sudo apt install curl

下文命令已用 curl 8.7.1 验证。其中可选的 --fail-with-body 示例需要 curl 7.76.0 或更新版本,见 curl 参数文档

第 2–4 步请在同一个终端里执行,以便继续使用前面定义的变量。

2. 保存页面,打印简短报告

先用一篇已经发布的英文文章练习。用于自己的部署时,把 page_url 换成实际公开地址:

check_dir=$(mktemp -d)
page_url='https://www.bobobk.com/en/rsync-preview-sync-workflow.html'

curl -sS -L --max-redirs 5 \
  --connect-timeout 10 --max-time 30 \
  -D "$check_dir/headers.txt" \
  -o "$check_dir/page.html" \
  -w 'status=%{http_code}\nfinal_url=%{url_effective}\nredirects=%{num_redirects}\ntotal_seconds=%{time_total}\n' \
  "$page_url"

-sS 隐藏进度条,同时保留错误提示。-D 保存响应头,-o 保存正文,让终端里的报告更容易阅读。-w 中的字段分别输出最终 HTTP 状态码、最终地址、跳转次数和总传输耗时,见 curl 的 write-out 指南

这篇示例文章应返回 status=200,最终 URL 也应符合预期。耗时会随网络变化。状态码只是第一项检查,还要确认下载的 HTML 确实是准备发布的页面。

两个超时参数的作用不同:连接建立阶段最多等待 10 秒,整个传输最多等待 30 秒。连接时间包含在总时间限制内,详见 curl 超时指南

3. 核对跳转与下载的正文

先查看保存下来的响应头:

grep -Ei '^(HTTP/|location:|content-type:|cache-control:|age:)' \
  "$check_dir/headers.txt"

发生跳转时,文件里可能包含多组响应头。-L 跟随 HTTP 重定向,--max-redirs 5 把本次练习限制为最多五次跳转。检查 Locationfinal_url,确认没有跳到意料之外的域名或登录页。curl 不会执行 JavaScript 跳转,见 重定向指南

再检查页面中一段容易辨认的文字:

if grep -Fq 'Rsync in Practice' "$check_dir/page.html"; then
  printf 'Expected article text found\n'
else
  printf 'Expected article text missing\n' >&2
fi

检查新部署时,应选择这次更新才加入的文字。昨天就存在的标题无法证明今天的修改已经上线。使用 CDN 时,响应头可能帮助解释旧内容的来源,但没有 Age 字段也不能证明请求完全没有经过缓存。

这里使用 GET 请求,以便检查正文。curl -I 发送的是 HEAD 请求,适合快速查看响应头,但不会下载文章内容,见 HEAD 参数说明

4. 让 shell 能识别 HTTP 错误

默认情况下,curl 收到 HTTP 错误页面后,仍可能返回表示成功的退出码。想保留错误正文,同时让 HTTP 错误触发失败,可以运行:

if curl -sS -L --max-redirs 5 --fail-with-body \
  --connect-timeout 10 --max-time 30 \
  -o "$check_dir/response.html" "$page_url"; then
  printf 'Transfer completed without a curl-reported error\n'
else
  curl_status=$?
  printf 'curl failed: exit=%s\n' "$curl_status" >&2
fi

遇到普通的 404 或 500 响应时,这个参数会让 curl 返回退出码 22;连接失败则有其他退出码。即使进入成功分支,也不能证明返回的就是预期文章。curl 的 响应指南 解释了 HTTP 状态与传输成功之间的区别。

旧版 curl 可以使用 --fail,前提是不需要保留错误正文。下一步的脚本直接检查 HTTP 状态,因此不依赖 --fail-with-body

5. 写成可重复使用的部署检查

在项目里保存为 check-page.sh

#!/bin/sh
set -eu

if [ "$#" -ne 2 ] || [ -z "$2" ]; then
  printf 'Usage: sh check-page.sh URL EXPECTED_TEXT\n' >&2
  exit 2
fi

page_url=$1
expected_text=$2
body_file=$(mktemp)
trap 'rm -f "$body_file"' EXIT
trap 'exit 1' HUP INT TERM

if http_status=$(curl -sS -L --max-redirs 5 \
  --connect-timeout 10 --max-time 30 \
  -o "$body_file" -w '%{http_code}' "$page_url"); then
  :
else
  curl_status=$?
  printf 'Transfer failed: curl exit=%s\n' "$curl_status" >&2
  exit 1
fi

if [ "$http_status" != '200' ]; then
  printf 'Unexpected HTTP status: %s\n' "$http_status" >&2
  exit 1
fi

if ! grep -Fq -- "$expected_text" "$body_file"; then
  printf 'Expected text missing: %s\n' "$expected_text" >&2
  exit 1
fi

printf 'OK: HTTP 200 and expected text found\n'

对示例文章执行检查:

sh check-page.sh \
  'https://www.bobobk.com/en/rsync-preview-sync-workflow.html' \
  'Rsync in Practice'

预期输出:

OK: HTTP 200 and expected text found

再换成一段不应该存在的文字:

sh check-page.sh \
  'https://www.bobobk.com/en/rsync-preview-sync-workflow.html' \
  'THIS_MARKER_SHOULD_NOT_EXIST_8e71'

这次应返回失败,并提示 Expected text missing。主动检查失败分支,可以发现“无论结果怎样都报成功”的问题。脚本针对公开 HTML 页面,明确要求 HTTP 200;如果接口正常情况下会返回其他状态码,需要按接口约定调整判断。

常见问题排查

现象 下一步操作
Could not resolve host 核对 page_url 中的域名,再执行 curl -v --connect-timeout 10 --max-time 30 "$page_url" 查看失败过程。
跳转次数超出限制 阅读已保存的 Location 响应头,修正循环跳转或域名配置。
HTTP 200,但找不到文字 打开保存的 HTML,检查是否返回了登录页、旧版本,或者正文需要 JavaScript 才能生成。
无法识别 --fail-with-body 使用上面的显式状态码检查脚本,或更新 curl。
证书验证失败 检查域名、系统时间和服务器证书链,部署检查时保留证书验证。

curl 检查的是响应字节,不会验证页面排版,也不会运行应用的 JavaScript。部署涉及这些功能时,还应在浏览器中打开页面检查。

把检查加入发布流程

发布完成后,用准确的公开 URL 和新内容独有的文字运行检查。发生异常时,保留响应头报告用于排查,并通过脚本退出码阻止后续自动化继续执行。命令稳定后,可以把它加入项目的 just 工作流

友情链接

其它