如果你是从 Ubuntu 或者 CentOS 7 直接跳到 RHEL 10 的,第一次打开终端大概率会觉得:这不还是 Linux 吗?ls、cd、cp 这些命令看起来一模一样,摸上去手感却完全不对——配置好的服务起不来,日志里的 Permission denied 查了半天才发现是 SELinux 的文件上下文问题;/tmp 里留的东西过个夜就消失;想用 locate 找文件,命令都装不上。等这些问题一个个冒出来,你才会意识到,RHEL 10 的"基础文件管理操作"早就不是简单的"增删改查"了,它背后牵扯着默认文件系统、安全策略、系统组件替换这些大事。
这篇内容我想用自己的实操经验,把 RHEL 10 上的文件管理从目录规划讲到权限、SELinux 上下文、归档压缩,中间穿插我在真实环境里踩过的坑和总结的习惯。适合刚接触 RHEL、或者从其他发行版迁移过来的朋友,也适合那些想把自己零散的文件操作知识系统捋一遍的人。
1. RHEL 10 的"基础"和你想的不太一样
1.1 默认文件系统变了,习惯也得跟着变
RHEL 10 的默认文件系统依然是 XFS。很多从 ext4 时代过来的人会忽略一个点:XFS 的 inode 是动态分配的,不像 ext4 那样格式化时固定数量,所以你几乎不会遇到"inode 耗尽"这种经典故障,但反过来,XFS 对大文件连续 I/O 的调优思路和 ext4 不一样。比如你习惯用 resize2fs 去缩扩容,XFS 只能用 xfs_growfs 且不能缩小,这是一个老生常谈但很多人仍会犯的错误。在 RHEL 10 里,/、/home 这种纯本地分区默认都是 XFS,如果你是重装系统时手动分区,别把 /boot 也搞成 XFS——虽然技术上能引导,但官方推荐使用安装器预设的文件类型,避免后续内核升级时踩引导坑。我自己一般在服务器规划阶段就确定好哪些目录要独立分区,哪些目录跟着根文件系统走,宁可在安装时多花十分钟,也不要在上线后再折腾迁移,那才是真正麻烦的开始。
另一个和文件管理直接相关的变化是 systemd 版本升级。RHEL 10 里 systemd 对临时目录的清理行为更加确定:systemd-tmpfiles 会清理 /tmp 下 10 天以上没动过的文件,而 /var/tmp 是 30 天。很多新人在 /tmp 里放临时脚本,第二天就没了,然后怀疑服务器被入侵或者有"神秘力量"删文件。真不是病毒,这只是系统自带的卫生习惯。理解了这个机制,你会更主动地去管好自己的文件路径,而不是把一切都丢给系统随机摆放。
1.2 那几个让人"意料之外"的新变化
前面说的 XFS 只是背景,真正影响你日常操作的是这几个变化。第一,RHEL 10 里默认包管理器已经是 DNF5,它比 DNF4 更快、内存占用更少,但配置文件风格略有调整,命令用法基本一致。和文件管理相关的点在于,DNF5 把事务历史和缓存目录管理得更干净,/var/cache/dnf 里不会再堆一大堆 Metadata,所以你想"手动清理缓存腾空间"之前最好先 df -h 看一眼,别一上来就 du -sh /var/cache/dnf 然后删掉一个本来就不大的目录。
第二,SELinux 在 RHEL 10 里默认强制开启(Enforcing),而且比以前更严格。这个放后面详述,但请记住一个原则:在 RHEL 上,文件能不能被读到,不只取决于权限位,还取决于安全上下文匹配不匹配。如果你以前习惯 chmod 777 解决一切,到 RHEL 10 这里真的行不通了。我见过太多把系统权限调成 777 之后,SELinux 照样拦截的例子,因为它拦的是"进程与文件之间的安全策略",权限位只是第一道门。
第三,RHEL 10 的镜像模式(Bootc)越来越普及,/usr 在镜像模式下是只读的,你没法像以前一样随便往 /usr/bin 里丢脚本。这其实是往容器思路走的结果,生产环境建议遵守"可执行程序放 /usr/local/bin,数据放 /var,配置放 /etc"这条铁律。如果你还在按照"把脚本丢进 /usr/bin、把数据库裸文件放根目录"的旧习惯来管理文件,在 RHEL 10 上会越来越难受。
2. 目录规划和 FHS:在 RHEL 10 上知道东西放哪
2.1 先看懂根文件系统的布局
ls / 之后你会看到 /bin -> usr/bin、/lib -> usr/lib、/sbin -> usr/sbin,这些都是合并之后留下的兼容链接。实际上从 RHEL 7 开始 /bin 就是 /usr/bin 的快捷方式,看目录别被迷惑。真正需要关心的目录是这几个:/etc 是机器级配置文件,任何软件装上去都会往这里写,比如 /etc/nginx/、/etc/ssh/;/var 存放会变的数据,/var/log、/var/lib、/var/cache、/var/tmp 都归它管;/home 和 /root 是用户数据区,root 的家目录是 /root,不是 /home/root,这个也算老坑;/usr/local 和 /opt 是手动安装软件时的"合法公民"区域。
理解这套布局,不是为了背诵,而是为了出问题时知道去哪里翻。举个例子,Nginx 起不来,你第一反应应该是看 /var/log/nginx/error.log 和 /var/log/messages,而不是翻 /usr/share/nginx/ 下的样例配置。做备份时,/var 往往是最大头,最好用 rsync 排除掉 /var/cache、/var/tmp 这类可重建内容,只保留真正需要保留的 /var/lib、/var/log 里的有效数据。这些判断在你熟悉目录职责后就是下意识行为。
2.2 /usr/local 和 /opt 怎么选
这是个简单但很多人纠结过的问题。我的习惯是:自己写的小脚本、从源码编译安装的单个工具,放 /usr/local/bin。那种"一套完整应用、包含多个目录和依赖、还要自更新"的东西,比如某些商业软件的 Linux 版,放 /opt/ 下一整个目录,然后在 /usr/local/bin 里做软链接。而 /home/user/bin 不是系统级选择,除非你只是想给自己用的工具,记得把 ~/.local/bin 加进 PATH。
在 RHEL 10 上如果你自己编译安装软件,最好指定 --prefix=/usr/local,避免搞乱发行版管理的 /usr。你可能觉得多此一举,但当你装了某个软件,日后 dnf update 的时候它和系统包产生文件冲突,你就知道这个边界有多重要。还有一个容易被忽略的点:放 /usr/local/bin 的脚本,SELinux 上下文不一定对,如果脚本需要读取用户家目录或者监听端口,记得检查 ls -Z 和对应域,必要时 restorecon 一下,这算是 RHEL 上"自己装软件"和"用包管理器装软件"的一个隐藏差异。
2.3 /tmp 和 /var/tmp 的清理机制差异
前面提过 systemd-tmpfiles 的 10 天和 30 天差异,这里再细致一点。你如果在服务器上跑定时任务,千万不要把中间结果写进 /tmp,跨天任务全部放 /var/tmp,不过 /var/tmp 也只有 30 天。更稳的做法是建一个 /var/lib/myapp/ 目录,用 systemd-tmpfiles.d 自己管理清理策略,比如只保留 3 天。说实话,对生产服务器,"临时目录由系统随机清理"这个行为本身就不是可预期的,提前规划好才是文件管理的正解。
我自己就吃过一次亏:当时给一个数据同步脚本把中间文件写在 /tmp,脚本设计成断点续传,结果某天重启后 /tmp 被清了,脚本从零开始传,浪费了整整一晚上带宽。后来索性把所有中间状态移到 /var/lib/syncer/,用 tmpfiles.d 配了 2 天清理,再也没出过这类问题。你如果也有类似的长任务,最好现在就检查一下脚本里的临时文件路径。
3. 从 ls 到 stat:每个文件背后的"身份证"
3.1 alias ll 背后发生了什么
RHEL 默认会给 root 配一堆别名:ll 就是 ls -l --color=auto,la 是 ls -a,l 是 ls -d .* 之类。很多人从 Ubuntu 过来直接敲 ll 就能用,因为 RHEL 的 /root/.bashrc 和 skel 里预置了这些别名。但这有个不起眼的坑:非 root 的新用户第一次登录,如果 .bashrc 是从 skel 复制过来的,别名也在;但如果是系统管理员手动创建的旧模板,可能没有 ll。所以脚本里千万别用 ll,要写就写全 ls -l,否则换个账号直接报 command not found。
ls 的常用参数里,记住两个最重要的组合:ls -lh,人类可读大小,看清 KB/MB/GB;ls -lt,按修改时间排序,最近改的排最上面,查日志特别好用。RHEL 10 的 ls 默认带 --color=auto,终端里目录、普通文件、可执行文件的颜色都不一样,刚开始可能会觉得花哨,但适应之后扫一眼颜色就能判断类型,效率提升很大。如果你在脚本里解析 ls 输出,记得加 --color=never 或者干脆别解析 ls,用 stat、find 更稳。
3.2 stat 才是看清文件全貌的工具
很多教程只讲 ls -l,但真正做排障的时候 stat 比 ls 有用得多。stat /etc/hostname 会显示:文件大小、占用块数、设备、Inode 编号、Links 数、Access/Modify/Change 时间和属性(Birth)时间。这里被问得最多的就是 atime、mtime、ctime 的区别。mtime(Modify)是内容最后被修改的时间,ls -l 显示的是它;ctime(Change)是 inode 本身元数据最后改变的时间,包括 chmod、chown、硬链接数变化,都会刷新 ctime;atime(Access)是最后被读取的时间,很多系统为了省 I/O 已经用相对 atime 代替。
所以排查"这个文件最近到底被谁动过"时,stat 是你第一个要抄起的工具。配合 find -printf '%T+ %p\n' 可以按时间精确列出文件,比 ls -l 强大太多。我给个经常用的例子:想查看某个目录下所有文件按修改时间排序,用 find 而不是 ls 递归,因为 find 能把子孙目录一起列出来,管道给 sort 也很方便。
find /data -type f -printf '%T+ %p\n' | sort -r | head -20这个命令我现在基本每天都用,做日志分析、找最近被改过的配置文件,比打开编辑器一个个看快得多。
3.3 用 touch 控制时间戳的小把戏
touch 不只是"创建空文件",它还可以改 atime 和 mtime。比如 touch -d '2025-01-01 10:00' /etc/some.conf 能把文件的修改时间改成指定时间。这个技巧在什么时候有用呢?某些守护进程会周期性检查配置文件的 mtime,发现变化就自动 reload,你如果只是临时改一下配置、又不想触发 reload,可以把 mtime 改回去。但我要提醒一句:这种用法是"绕弯"操作,掩盖了真实变更记录,生产环境慎用,除非你非常清楚自己在干什么。
另外,批量创建占位文件也常用 touch。比如要测试一个脚本对大量文件是否健壮,直接 for i in {1..1000}; do touch file_$i.txt; done,几秒钟生成一千个空文件,比手动建目录方便得多。类似地,mkdir -p a/b/c 这种递归创建目录,也需要熟悉,配合 touch 可以快速搭出要测试的目录结构。
4. 复制、移动、删除:三大高频操作的正确姿势与隐藏坑
4.1 cp 的 -a 和 -p 差在哪
RHEL 10 的 cp 来自 coreutils 9.x,行为比老版本严格。三个高频参数:-r 递归复制目录,但它默认是"跟随软链接"的,如果你复制一个带软链接的目录,想保留链接本身,得加 -d 或干脆用 -a;-p 保留属主、属组、权限和时间戳;-a 等于 -dR --preserve=all,包含权限、时间戳、属主属组、ACL、xattr 以及 SELinux 上下文。这是"完整克隆"的最佳选择。
我最常和别人强调的场景是备份网站目录:如果你用了 cp -r 而不是 cp -a,SELinux 上下文几乎一定会丢,导致新目录里的文件类型变成 default_t,Nginx 或 Apache 直接 403 Permission denied。在 RHEL 上备份还原配置文件、网站目录、数据目录,请一律 cp -a。这个教训我当年是在客户现场踩的:迁移一个 Drupal 站点,cp -r 过去之后页面全部 403,我在权限、属主上面排查了一个多小时,最后 ls -Z 一看,文件标签全是 default_t,restorecon 一下就好了。这种坑,写文档的人不会讲,但实际生产里非常常见。
4.2 mv 跨文件系统时发生了什么
mv 给人的直觉是"移动",同一文件系统内它确实只是改个路径名,速度飞快。但跨文件系统(比如从 /home 移动到 /mnt/data)时,内核会把它翻译成 cp + unlink:先完整复制数据,再删除源文件。结果就是:大文件跨分区 mv 会非常慢,而且瞬间占用两块磁盘容量;数据到新位置后 inode 完全变了,硬链接失效,ACL 和 SELinux 上下文也可能需要重新确认。
所以做"从系统盘迁移数据到数据盘"这种常见操作时,我建议用 rsync 而非 mv:先 rsync 到目标目录,校验无误后手动清源,比 mv 更可控,也避免 mv 中途出错导致源文件已删了半截的尴尬。有一次我在生产环境把一个大目录从根分区移动到数据盘,mv 执行到一半磁盘快满,系统直接告警,吓得我赶紧停掉。后来改成 rsync 分批同步,完事再删源,再也没出现过这种险情。
4.3 删除操作的风险控制与替代方案
rm -rf 是每个 Linux 用户都熟记于心又心惊胆战的命令。RHEL 10 里 rm 默认没有任何回收站概念,删了就是删了。我自己的习惯:遇到不确定内容的目录,先 ls -A 或者 find . -maxdepth 1 -type f 看一眼再删;能用 find -delete 删除大批文件时,先 find ... -print | head 确认清单;删除超过一个目录的内容,写完整路径,绝对不要用 rm -rf /xxx/yyy/ 加空格,也绝对不要手滑在 cd 错地方之后执行 rm -rf *。
更安全也更推荐的做法是装一个 trash-cli,把 rm 变成"移入回收站",核心业务服务器上尤其值得。虽然这会改变命令语义,但现代 RHEL 上大多数人是可以接受的,毕竟数据删错成本远高于一条命令的语义洁癖。如果你不想改变习惯,至少给自己立个规矩:涉及到删除的自动化脚本,一律先加 --dry-run 或者在命令前 echo 一下,打印将要删的清单,人工确认后再真正执行。
5. 查找的进阶:find 命令的 RHEL 实战组合
5.1 基础查找:find 的常用参数一口气讲清
find 是文件管理里技术含量最高的命令,值得当重点。语法是 find 路径 测试条件 动作。常用条件:-name '*.conf' 按名称(可用通配符);-type f/d/l 按类型;-size +100M 大于 100M;-mtime -1 24 小时内修改过、-mtime +30 30 天以上没修改过;-user root、-group wheel 按属主属组;-perm /4000 带 setuid 位或 setgid 位的文件;-empty 空文件和空目录。组合逻辑上,find 默认条件是"与",-o 表示"或",-not 取反。
举个例子,查看 /var/log 下最近 3 天被改过的所有普通文件:
find /var/log -type f -mtime -3如果是查大文件塞满磁盘,我常干的一招:
find / -xdev -type f -size +1G -exec ls -lh {} \;-xdev 表示不跨挂载点,避免把 /proc、/dev 这些虚拟目录也扫一遍,速度快几个数量级,而且不会报一堆 pointless 错误。如果你从来没加过 -xdev,第一次在真实服务器上跑 find / 大概率会被 /proc 下的海量文件刷屏,然后你还以为系统出问题了。
5.2 find + exec 的实用案例
find -exec 是用 find 结果作为另一条命令的输入,两种写法:-exec 命令 {} ; 每个文件执行一次;-exec 命令 {} + 把结果攒一批执行一次,后者性能好很多,几乎总是应该用它。真实案例:清理 /var/log 下所有 30 天前的 .log.gz:
find /var/log -type f -name '*.log.gz' -mtime +30 -exec rm {} +在 RHEL 10 上用 find 批量改权限也常有,比如把某个目录下所有 .php 文件统一成 644:
find /var/www/html -type f -name '*.php' -exec chmod 644 {} +注意,find 默认不会自动跟随软链接,如果希望它跟随,加 -L,或者用 -P 明确不跟随。后者是默认,但我见过不少人在有软链接的目录树里用 find 结果预期不符,就是因为没搞清这一点。另外,-name 匹配的是文件名部分,不含路径前缀;要用 -path '/public/.html' 匹配完整路径,这个也容易踩。比如你想找 /data 下所有在 public 子目录里的 html,直接 -name '*.html' 会多出一堆不在 public 下的文件,写 -path 就好很多。
5.3 小文件查找用 plocate 更快
find 适合精确定位,但如果你只是"我记得有个文件名大概叫 xxx"这种模糊需求,全盘 find 会等到怀疑人生。RHEL 10 的仓库里有 plocate,装完先 updatedb 建立索引,之后 plocate somefile 一秒出结果。需要注意:updatedb 默认会跳过 /proc、/sys、/run 等虚拟目录,也会跳过挂载点,所以刚挂载的新盘内容不会进索引,得手动 updatedb;索引库通常在 /var/lib/plocate/plocate.db,会随系统更新自动重建。如果你是从 CentOS 7 迁移过来的,过去 mlocate 的 alias 和 crontab 策略在 RHEL 10 上不通用,建议直接习惯 plocate。
实际使用中,plocate 最适合的场景是"快速定位配置文件"。比如你忘了 Nginx 的默认站点配置在哪,plocate nginx.conf 一下,基本能找到 /etc/nginx/、/usr/share/doc/ 等所有路径。但要注意 plocate 只按文件名匹配,不支持按内容搜索,想按内容搜还是要用 grep -r 或者 ripgrep。两者配合起来效率很高:plocate 找文件,rg 找内容。
6. 链接:硬链接和软链接的底层区别
6.1 先搞懂 inode 再谈链接
Linux 文件系统的核心概念是 inode:每个文件或目录都对应一个 inode,里面存着元数据和数据块的指针,而"文件名"只是 inode 的一个引用入口。硬链接的意思就是"同一个 inode 增加一个文件名",所以硬链接创建后,ls -l 里 Links 数字会加一,两个名字指向同样的数据块,修改任何一个,另一个同步变化,删除一个只减少链接计数,最后一个链接被删除时数据才真正释放。
硬链接的限制很明确:不能跨文件系统,因为不同分区的 inode 编号体系独立;不能链接目录,内核为了防止目录形成环路。软链接(符号链接)则是创建一个新文件(自己的 inode),内容指向目标路径,目标可以是文件、目录,也可以跨文件系统。如果你看到 ls 输出里 l 开头的权限位,那就是符号链接。理解这一层,你就不会再问"为什么 ln -s 之后 df 显示磁盘空间没变化"这种问题了,符号链接本身占用的空间极小,它只记录一个目标路径字符串。
6.2 什么时候用哪个
实际选择建议:同一文件系统内、想省空间、想同步多目录下的同一文件,用硬链接,cp -l 可以快速建立硬链接副本;想让程序或脚本通过一个通用名字访问可变位置的库或二进制,用软链接,比如把 /opt/app/bin/foo 软链到 /usr/local/bin/foo。这个简单原则很多人知道,但 RHEL 上有一个额外点:SELinux 对硬链接的检查在 RHEL 10 中更严格,硬链接被访问时内核会校验关联 inode 的安全上下文,如果上下文不一致,可能出现"文件明明有权限却打不开"的情况。所以生产中给服务加软链接时,记得用 ls -Z 确认链接和目标的上下文。
我举个例子:你编译了一个工具放在 /opt/webtool/bin/webtool,想全局调用,就 ln -s /opt/webtool/bin/webtool /usr/local/bin/webtool。但如果 /usr/local/bin 和 /opt/webtool 所在分区上下文不同,或者你原有 /usr/local/bin 的标签被改过,调用时可能被 SELinux 拦。我碰到过一次:/usr/local/bin 标签正常,但目标目录 /opt/webtool 因为是从别处复制过来的,标签是 default_t,结果怎么都执行不了。恢复方式很简单:semanage fcontext -a -t bin_t '/opt/webtool(/.*)?' 然后 restorecon -Rv /opt/webtool,马上就好。
6.3 复制和删除链接时的常见坑
cp 遇到符号链接的默认行为是"跟随链接、复制目标内容",这会让很多人拿到一堆"看起来像链接其实是普通副本"的文件。想要保留链接本身,用 cp -d 或 cp -a;tar 打包时默认不跟随,但解包后链接也要小心目标路径不匹配的问题。删除符号链接也有讲究:rm link 删掉的是链接文件本身,不会删除目标;但如果你写 rm link/,rm 会尝试进入目录然后删掉目标目录里的内容,绝对不要在符号链接上带斜杠执行删除。这个细节写在 man 里,但踩过的人都知道什么叫"一条命令清了半台服务器"。
如果你需要一次性复制一大块目录并且保留原有的链接结构,我的建议是用 tar 管道而不是 cp -r。比如想要把 /data 复制到 /backup/data,保留所有软链接和权限:
cd /data && tar cf - . | (cd /backup/data && tar xpf -)这样比 cp -a 更可控,尤其是面对特殊文件名、xattr 这些场景时,tar 的保留能力更强。当然,跨机器传输时也常用 rsync,但 tar 管道这种单机复制手法快速可靠,值得掌握。
7. 权限管理与 SELinux 上下文:RHEL 10 的文件安全
7.1 常规权限:chmod、chown、umask 速查
文件权限位分三组:属主(u)、属组(g)、其他(o),每组读 r、写 w、执行 x。RHEL 上我几乎只用数字表示:755 是 rwxr-xr-x,644 是 rw-r--r--。需要给脚本加上执行权限就是 chmod +x;希望所有人都能读但不能写就是 chmod 644。umask 决定新建文件的默认权限。RHEL 10 里 root 的默认 umask 是 0022,所以新建文件默认 644、目录默认 755;如果系统上配了 0002(常见于共享目录场景),新建文件就会是 664。手动建共享目录时,最好显式 umask 002 再 mkdir,否则同事上传的文件别人改不了,这算是最常见的协作权限问题之一。
chown 命令记住一个坑:chown user:group 中 group 那部分如果省略,比如 chown alice file,只会改属主不碰属组;想都改就写全。RHEL 10 上 chown 的符号用法 chown alice:staff 已经很稳定,bash 的冒号不会被误解,放心用。另一个容易被忽略的细节是,chown 和 chmod 都会改变文件的 ctime(Change 时间),如果你在做取证或者审计,看到 ctime 变了就知道权限或属主被动过,即使内容没改。这也是 stat 命令在排障里比 ls 有价值的原因之一。
7.2 ACL:给特定用户单独开权限
传统的 ugo 权限粒度太低,比如"让 backup 用户能读 /var/log/nginx 目录,但其它人不行"这种需求,就得用 POSIX ACL。RHEL 10 的 XFS 默认支持 ACL,不用额外挂载参数。给用户加读权限:
setfacl -m u:backup:r-- /var/log/nginx/查看:
getfacl /var/log/nginx/递归给目录里所有文件加权限:
setfacl -R -m u:backup:r-- /var/log/nginx/ACL 生效后,ls -l 末尾会出现一个加号,这是排查问题的第一条线索。还要注意 cp 时如果不加 -p 或 -a,ACL 会丢失;rsync 必须显式加 -A 才能保留 ACL,加 -X 保留 xattr,不加的话这些扩展属性全会丢。很多运维把 rsync -avz 当成"全能备份",其实 -a 只包含 -rlptgoD,并不包含 ACL 和 xattr,这是一个文档里写得很清楚但经常被人忽略的陷阱。
7.3 SELinux 上下文:RHEL 上文件突然不可访问的头号原因
这是我在 RHEL 排障中见到最多的一类问题:权限、ACL、属主全对,Web 服务还是 403,SELinux 审计日志一翻全都是 avc: denied。RHEL 10 默认 Enforcing,每条文件操作除了检查权限位,还要核对文件的安全上下文和进程的域是否匹配。常见的文件类型标签有:etc_t 对应 /etc 下的配置文件;httpd_sys_content_t 是 Web 服务可以读取的内容;httpd_sys_rw_content_t 是 Web 服务可读写的目录;home_root_t、user_home_t 对应用户家目录;var_log_t 对应 /var/log。
新问题多半出在"自己动手新建了一个目录":比如你在 /data/web 下建了站点目录,没做任何标签处理,类型通常是 default_t,Nginx 一访问就被 SELinux 拦住。解决办法用下面的命令给目录打上正确标签并让其持久生效:
semanage fcontext -a -t httpd_sys_content_t '/data/web(/.*)?' restorecon -Rv /data/websemanage 命令没有就用 dnf install policycoreutils-python-utils 装。如果你只是临时测试,chcon 可以改标签但不会持久,系统文件恢复时会还原,正式环境一律用 semanage fcontext 加 restorecon 组合。日常查看文件安全上下文很简单:ls -Z;查看进程域用 ps -Z。写服务启动脚本经常遇到的问题就是脚本放在 /tmp 下、上下文是 tmp_t,SELinux 直接拒绝脚本访问家目录,所以我的习惯是:自己的脚本一律放 /usr/local/bin 并 restorecon,宁可多一步也不和 SELinux 对着干。
如果你觉得 SELinux 麻烦,RHEL 10 上不建议关闭它,现在容器、虚拟化、Web 服务都和 SELinux 有绑定的策略。关掉之后短期内不会出事,但一旦出事,日志里少了 avc 拒绝信息,排查难度反而更高。保持开启,学会看 audit.log,比任何关闭技巧都靠谱。
8. 归档与压缩:tar 命令在 RHEL 10 下的标准动作
8.1 tar 的常用组合与参数解读
tar 最早的用途是磁带有挡位(Tape ARchive),现在就是打包加压缩。RHEL 10 上最常用组合:创建压缩包 tar -czvf backup.tar.gz /var/log;解压 tar -xzvf backup.tar.gz。参数拆开看:c 创建、x 解压、z gzip 压缩、v 显示过程、f 指定文件名(f 必须在最后且参数是一个文件名)。这种写法是几乎所有教程的标准,但在 RHEL 10 上我更推荐直接省略 v:几十万文件的时候 v 会把终端刷爆,真正想看进度用 --totals 或者终端里另开一个 iotop 观察。
解压到指定目录更常用:
tar -xzf backup.tar.gz -C /tmp/restore在 RHEL 上打包时必须意识到 SELinux 上下文是个值得保留的属性。GNU tar 有 --selinux 和 --xattrs 参数,打包时建议写全:
tar --selinux --xattrs -czf mydata.tar.gz /data/app解压时同样带上这两个参数:
tar --selinux --xattrs -xzf mydata.tar.gz -C /tmp/restore这样恢复出来的文件才带着原始上下文,可以免去 restorecon 这一步。如果你忘记加 --selinux,解压后记得跑 restorecon -Rv /data/app。另外 tar 默认不跟随符号链接,所以打包时符号链接会原样存下来;如果想把链接指向的真实内容也打进去,用 -h。这个选择取决于你要迁移原始结构还是拉平文件。
8.2 备份恢复中容易忽略的点
备份 web 目录时,建议 tar 排除掉 runtime 文件,比如 socket、cache、log:
tar --selinux --xattrs -czf site.tar.gz --exclude='*.log' --exclude='.cache' /var/www/html恢复大包之前,先确认目标目录为空——tar 解到已存在的目录时会覆盖相同路径、不会自动清掉多余文件,这常常导致"旧的废弃配置还在但你没注意到"。我见过最典型的场景:把一份备份恢复到原目录,结果原来已经删掉的旧配置文件被保留下来,新配置文件覆盖上去,两边配置混在一起,服务行为完全不可控。所以恢复前先清空目标目录,或者用一个全新的目录来承接解压结果。
如果在 RHEL 10 上用 tar 备份其它机器传来的包,记得先确认来源端的信息。你永远不知道对方打出来的是一个顶层目录还是散装文件,所以先解到独立目录里查看结构,再决定路径,成本很低但能避开大半解包事故。比如你原本以为解出来是 /site-bak,结果人家打包时没用顶层目录,直接解出一堆散落文件到当前目录,你的 /tmp 下立刻变得一团糟。这种事我踩过两次,之后就养成了"永远先解压到临时目录查看"的习惯。
8.3 快速用 rsync 同步目录的小例子
rsync 实际也是基础文件管理里的高频工具,不展开太多,给一个我日常同步网站的模板:
rsync -avz --delete /var/www/html/ user@remote:/var/www/html/-a 归档模式保留权限、时间戳,-v 列出同步清单,-z 压缩传输,--delete 会让目标目录删除源端已不存在的东西。注意两个细节:源目录末尾的斜杠含义不同——带斜杠时同步目录内容,不带时同步目录本身,写错通常会造成多一层目录;想保留 ACL 和 xattr 要加 -A -X,只是普通文件管理场景可以不加。生产环境同步大目录前,先 rsync -avz --dry-run 走一遍,看它准备删多少、传多少,确认无误再去掉 --dry-run。这个习惯能把你从"一夜之间整个目录被同步到空目录"的灾难里救出来。
我现在不管在客户现场还是自己的服务器上,涉及任何批量文件操作,第一反应都是先跑 dry-run 或者 find 列清单,确认范围后再动真格的。基础文件管理看似简单,但真正决定你会不会在凌晨三点被监控电话吵醒的,往往就是这些"多看一眼"的习惯。