直接把新文件复制到活动的静态目录上,会造成一段访问者可能从一个版本拿到 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 或符号链接模式可以收紧切换;在依赖更强断言之前,请测试确切的文件系统与服务器行为。
验证公共边缘
切换之后,请求首页、一个深层路由、一个带指纹的资源与一个缺失路径。把公共字节与预置制品比较。在检查完成与观察窗口结束之前,保留回滚目录。
来源
- POSIX
rename(),名字替换语义,已核验 2026-08-23。 - Linux
rename(2),文件系统与替换行为,已核验 2026-08-23。 - GNU tar manual,归档创建与解包,已核验 2026-08-23。