直接把新文件复制到活动的静态目录上,会造成一段访问者可能从一个版本拿到 HTML、从另一个版本拿到资源的时期。更安全的模式是:在活动树旁预置一棵完整的树,验证它,再改变目录名。

把所有发布目录放在同一文件系统上

当活动树、预置树与回滚树共享同一文件系统与父目录时,名字替换最强。先检查:

df -P /srv/www

在该父目录下创建唯一命名的中转目录。不要把未解析的变量或宽泛通配符当成删除目标来复用。

stage=$(mktemp -d /srv/www/site.new.XXXXXX)

填充并验证预置目录

把生成制品复制进空目录,然后检查代表性文件与期望的文件数:

tar -C public -cf - . | tar -C "$stage" -xf -

test -s "$stage/index.html"
test -s "$stage/404.html"
find "$stage" -type f | wc -l

当工具支持目录参数时,对预置路径运行链接与校验和检查。未通过验证的预置目录绝不能获得活动目录的名字。

用显式回滚路径切换名字

在第一次移动前解析每个路径:

live=/srv/www/site
stamp=$(date -u +%Y%m%dT%H%M%SZ)
rollback=/srv/www/site.old-$stamp

test -d "$live"
test -d "$stage"
test ! -e "$rollback"

mv "$live" "$rollback"
if mv "$stage" "$live"; then
  test -s "$live/index.html"
else
  mv "$rollback" "$live"
  exit 1
fi

这段序列在两个移动之间留下一个短窗口。对每次请求都对根的单一静态服务进程来说,该窗口通常很小但仍可观察。平台特定的 rename 或符号链接模式可以收紧切换;在依赖更强断言之前,请测试确切的文件系统与服务器行为。

验证公共边缘

切换之后,请求首页、一个深层路由、一个带指纹的资源与一个缺失路径。把公共字节与预置制品比较。在检查完成与观察窗口结束之前,保留回滚目录。

来源