备份包只有 1.5K?

改 OpenResty 配置之前我做了备份。备份包躺在目录里,1.5K。

这台机器不是我一个人的。1Panel 面板上挂着 9 个站点,我自己的 3 个,别人的 6 个。我那三个域名是 h5.example.com、api.example.com、admin.example.com。

在这种机器上,任何一次 nginx -s reload 都在同时动 9 个业务。所以我先备份,再改配置。给的那条命令是这一条。

bash 复制代码
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。一个空备份和一份有效备份,在命令行回显上长得一模一样。

哪一刻确认它等于没备份

让我确认的是这条命令。

bash 复制代码
tar -tzf "$BK" | grep -E "example\.com"

没有任何输出。

tar -tzf 列出包内文件清单,grep 拿域名关键字去筛,一个站点都没有。那时候我正准备改一个 OpenResty 配置,改错就要回滚,而回滚依据的那个包里一片空白。同机 6 个别人的站点正跑着。

验收标准只有一个,我要保的域名在不在包里

这件事给我的教训不是「命令写错了」。一个 1.5K 的包确实存在,可它承诺不了任何东西。所以验收动作得回答一个具体问题:我要保的那几个域名,在包里吗?

正确打包,是把 find 的结果整体交给 tar,而不是取一条再 dirname。

bash 复制代码
BK=/opt/1panel/backup; TS=$(date +%Y%m%d_%H%M%S); mkdir -p "$BK"

# ① 全量打包:find 的结果通过 -T - 从 stdin 交给 tar,绕开参数展开与空格问题
find /opt/1panel -name "*.conf" -type f 2>/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 -E "example\.com"

-T - 这处是关键。tar 从标准输入读文件列表,绕开了 $(...) 展开带来的参数个数上限和文件名空格问题。如果路径里可能有空格,用 -print0 与 --null 配对。

bash 复制代码
find /opt/1panel -name "*.conf" -type f -print0 2>/dev/null \
  | tar -czf "$BK/openresty_all_$TS.tar.gz" --null -T -

验证这一步不是可选项,它是备份的一部分。只做打包、不做验证,和那条 head -1 命令没有本质区别,你只是换了一种方式不知道自己备份了什么。

还有一点不显眼但很要命:备份包要带时间戳命名,就是上面命令里的 $TS。它不是为了归档整齐,而是为了不覆盖上一份。你永远不知道上一份是不是唯一一份还有效的。

顺带一条,怎么确认真正生效的配置在哪个文件

面板托管的 Nginx,配置文件位置不一定是你以为的那个。这条命令能 dump 全部生效配置,并把每一段配置的来源文件打出来。

bash 复制代码
docker exec <面板web容器> nginx -T 2>&1 \
  | sed -n 's/^# 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 能打出每一段配置的来源文件,这是该备份哪些文件的权威清单。

备份不做验证,那张包就是空的。

相关推荐
无足鸟ICT2 小时前
【RHCA+】RPM包验证和数字证书
linux·运维·服务器
erzong2312 小时前
Linux操作系统:线程概念与控制
linux·算法
星恒随风2 小时前
Linux线程概念详解:从分页存储、页表、MMU与TLB,深入理解线程和进程的区别与联系
linux·运维·笔记·学习·状态模式
小范的技术工坊2 小时前
Linux应用开发(文件IO)
linux·stm32·单片机
小范的技术工坊3 小时前
Linux应用开发(文件属性)
linux·运维·服务器
wuminyu3 小时前
JMM学习总结:深入理解happens-before关系
java·linux·c语言·jvm·c++
开开心心就好3 小时前
多份文档怎么批量打印?支持多种格式
java·服务器·开发语言·pdf·ocr·散列表·启发式算法
姜鱼问生4 小时前
每次开机手动检查 6 样东西?我写了个 2 秒自检脚本
运维·网络·nginx·docker·容器
钱工的门窗技术笔记4 小时前
智能门窗的边界与前提:为什么“智能”不能替代本体性能
网络·物联网·智能家居