
改 OpenResty 配置之前我做了备份。备份包躺在目录里1.5K。这台机器不是我一个人的。1Panel 面板上挂着 9 个站点我自己的 3 个别人的 6 个。我那三个域名是 h5.example.com、api.example.com、admin.example.com。在这种机器上任何一次 nginx -s reload 都在同时动 9 个业务。所以我先备份再改配置。给的那条命令是这一条。tar-czf$BK$(dirname$(find /opt/1panel-name*.conf-path*conf.d*2/dev/null|head-1))跑完 ls -lh 一看。-rw-r--r-- 1 root root 1.5K Sep 22 20:41 openresty_backup.tar.gz九个站点的配置压缩完 1.5K。这个数字本身就在报警。可我当时接下去做的事是改配置不是打开包看看。这条命令我是怎么想出来的拆开看里头叠了三层错。单看每一层都像个好习惯。第一层出在 -path “conf.d”。我一开始想的是「站点配置都在 conf.d 里」就先拿 -path 筛了一遍。可 /opt/1panel 下面不止一个 conf.d面板自己的、镜像默认的、各个应用目录里都有。这个条件没能帮我定位到站点配置只是把候选集缩成了一堆同名目录。第二层是 | head -1。这层最致命。find 的输出顺序取决于文件系统怎么遍历不是按重要性排的也不保证稳定。第一条是谁不知道。第三层是 $(dirname …)。它把「一个文件」换成了「一个目录」然后只备份这一个目录。三层叠起来的结果是find 找到的第一个 .conf 所在的那个目录被打包其余全都不进包。而它实际取到的是面板或者镜像自带的那个默认 conf.d里面是出厂配置不含任何站点配置。两个目录的挂载关系是这样。宿主 /opt/1panel/www ── 容器内 /www 宿主 /opt/1panel/www/conf.d ── 容器内 /usr/local/openresty/nginx/conf/conf.d真正要备份的站点配置在 /opt/1panel/www/… 这一支上我取到的是另一支。还有第四层也是最该记住的一层。我没验证。tar 不报错ls 显示文件存在退出码是 0。一个空备份和一份有效备份在命令行回显上长得一模一样。哪一刻确认它等于没备份让我确认的是这条命令。tar-tzf$BK|grep-Eexample\.com没有任何输出。tar -tzf 列出包内文件清单grep 拿域名关键字去筛一个站点都没有。那时候我正准备改一个 OpenResty 配置改错就要回滚而回滚依据的那个包里一片空白。同机 6 个别人的站点正跑着。验收标准只有一个我要保的域名在不在包里这件事给我的教训不是「命令写错了」。一个 1.5K 的包确实存在可它承诺不了任何东西。所以验收动作得回答一个具体问题我要保的那几个域名在包里吗正确打包是把 find 的结果整体交给 tar而不是取一条再 dirname。BK/opt/1panel/backup;TS$(date%Y%m%d_%H%M%S);mkdir-p$BK# ① 全量打包find 的结果通过 -T - 从 stdin 交给 tar绕开参数展开与空格问题find/opt/1panel-name*.conf-typef2/dev/null\|tar-czf$BK/openresty_all_$TS.tar.gz-T-ls-lh$BK/openresty_all_$TS.tar.gz# ② 必须验证列得出域名才算备份成立tar-tzf$BK/openresty_all_$TS.tar.gz|grep-Eexample\.com-T - 这处是关键。tar 从标准输入读文件列表绕开了 $(…) 展开带来的参数个数上限和文件名空格问题。如果路径里可能有空格用 -print0 与 --null 配对。find/opt/1panel-name*.conf-typef-print02/dev/null\|tar-czf$BK/openresty_all_$TS.tar.gz--null-T-验证这一步不是可选项它是备份的一部分。只做打包、不做验证和那条 head -1 命令没有本质区别你只是换了一种方式不知道自己备份了什么。还有一点不显眼但很要命备份包要带时间戳命名就是上面命令里的 $TS。它不是为了归档整齐而是为了不覆盖上一份。你永远不知道上一份是不是唯一一份还有效的。顺带一条怎么确认真正生效的配置在哪个文件面板托管的 Nginx配置文件位置不一定是你以为的那个。这条命令能 dump 全部生效配置并把每一段配置的来源文件打出来。dockerexec面板web容器nginx-T21\|sed-ns/^# configuration file \(.*\):$/\1/p|sort-u两点要注意。输出的是容器内路径要对照挂载关系换算成宿主路径比如 /www/… 换回 /opt/1panel/www/…。它回答的是「哪些文件被真正加载了」这正好就是你的备份清单该覆盖的集合。固化成几条能复用的判据打包这一步做法是 find 根路径 -name “*.conf” -type f -print0 交给 tar -czf 包 --null -T -。不用 head也不用 dirname 取单条。验证内容这步是 tar -tzf 包 再 grep -E “域名关键字”列得出生效域名才算过列不出来就回到打包那步重来。验证可解是 tar -xzf 包 -C /tmp/verify 之后 ls /tmp/verify看能不能解出目录树。确认配置来源还是用 docker exec 进面板 web 容器跑 nginx -T。再 sed 出 # configuration file 那几行去重。改前基线要逐个域名 curl 一遍参数是 -s -o /dev/null -w “%{http_code}” --max-time 8。再带上 Host 头打 http://127.0.0.1/全 200 或者 301 就记录下来。改后用同一条 for 循环再跑一次跟基线对照掉了就立刻回滚。语法门禁是 docker exec 进容器跑 nginx -t看到 syntax is ok 才 reload。基线和改后对照这两步在这台机器上尤其重要。它的粒度不是「我这个站点」而是「这台机上全部 9 个」。grep 的关键字要覆盖他人站点的域名不能只 grep 自己的。你动的这份配置影响的是整台机。剩下的几条我一起放在这里。find 加 head -1 取到的不是「一个代表」它是个「未知」备份要全量用 -T - 把清单整体交给 tar。1.5K 这个数字本身就是信号备份体积和常识不匹配的时候先停下来。nginx -T 能打出每一段配置的来源文件这是该备份哪些文件的权威清单。备份不做验证那张包就是空的。