关键是要用root执行sudo tar --acls --xattrs --selinux -xpf archive.tar.gz -c /target,并优先解压到空目录再迁移,避免覆盖引发权限冲突。

用 tar 做备份时保留权限,关键不是“加不加 -p”,而是搞清要保什么、在哪保、谁来保。很多服务启动失败、二进制无法执行、目录进不去,根源不是解压出错,而是权限和属主没真正还原到位。
基础权限与属主必须用 root + -p
普通用户解压再加 -p 也没用:属主会静默变成当前用户,setuid/sticky 位会被丢掉,web 目录可能没了 x 权限导致 403。只有 root 运行时,-p 才自动启用 --same-owner,并真正写入 UID/GID。
- 打包时不用特别处理(tar 默认记录权限和属主)
- 解压必须用
sudo tar -xpf archive.tar.gz -C /target - 目标路径不能是已有服务目录(如 /usr/local),优先解到空目录再迁移
- 解压前先看一眼归档内容:
tar -tzf archive.tar.gz | head -3,确认路径干净、没多出 /home/xxx/ 这类绝对前缀
ACL、扩展属性、SELinux 需额外参数
-p 只管传统权限(rwx、setuid、sticky),但数据库、容器、安全工具常依赖更深层的属性。缺了它们,audit 日志报 avc denied、ping 提示 Operation not permitted、目录被 chattr 锁死,都属于这类问题。
-
--acls:还原 getfacl / setfacl 设置的访问控制列表 -
--xattrs:还原扩展属性,包括 capabilities(如 cap_net_raw)、user.* 自定义键 -
--selinux:还原 SELinux 上下文(system_u:object_r:bin_t:s0),否则策略引擎直接拦截 - 推荐组合:
sudo tar --acls --xattrs --selinux -xpf archive.tar.gz -C /opt/app
避免覆盖引发的隐性权限冲突
业务报错很少因为 tar 命令失败,更多是因为解压后覆盖了运行中的配置、日志目录或已设权限的文件。比如 /etc/myapp/conf.d/ 被替换成旧版,或 /var/lib/myapp 的属主被重置为 root 导致服务进程无法写入。
- 别直接 -C /usr 或 -C /etc;先解到临时目录,再用 cp -a 或 rsync -aHAX 同步关键文件
- 必须覆盖前备份:
mv /opt/myapp /opt/myapp.bak.$(date +%s) - 检查挂载选项:
findmnt -D /opt,若目标分区挂了 noexec 或 nosuid,即使 -p 写入成功,内核也会在运行时忽略这些位
验证是否真还原成功
别只信命令没报错,得动手验证:
- 查 setuid/sticky:
ls -l /usr/bin/passwd看有没有 s(如 -rwsr-xr-x);ls -ld /tmp看有没有 t(如 drwxrwxrwt) - 查 ACL:
getfacl /path/to/file对比备份前后 - 查 capability:
getcap /usr/bin/ping应显示cap_net_raw+ep - 查 SELinux:
ls -Z /usr/bin/bash看 context 是否匹配原系统











