Appearance
文件管理
运维工作里最常见的操作基本都在文件层面:部署新版本要拷贝文件、排查报错要翻日志、磁盘告警要找大文件清理、改配置前要备份原文件。这些操作本身都不复杂,但边界情况特别容易踩坑——删了文件空间没释放、变量为空导致 rm -rf / 把系统删了、软链接断链服务静默出错、文件类型和扩展名对不上导致打不开。
日常运维大量时间都花在跟文件打交道:看内容、找位置、确认类型和权限、清理空间。
一、文件类型
ls -l 输出第一列的第一个字符,标记的就是文件类型。Linux 的设计哲学是"一切皆文件"——不光文本是文件,目录、设备、管道、socket 全都以文件的形式存在。
bash
ls -l /etc/passwd /etc /dev/null| 标记 | 类型 | 是什么 |
|---|---|---|
- | 普通文件 | 文本、二进制、压缩包等等 |
d | 目录 | 目录本身也是个文件,记录包含的文件名和 inode |
l | 软链接 | 指向另一个路径的"快捷方式" |
c | 字符设备 | 按字符流读写的设备,比如终端、串口 |
b | 块设备 | 按数据块读写的设备,比如硬盘 |
s | socket | 进程间通信用的套接字文件 |
p | 管道 | 命名管道(FIFO),用于进程间数据传输 |
光看后缀名判断文件类型经常翻车,正确做法是用 file 命令看真实内容:
bash
file /bin/ls # ELF 可执行文件
file /etc/passwd # ASCII 文本
file app.log # 可能是文本、压缩包,或者编码不对的二进制排查"日志打不开"的时候,先 file 看一眼实际类型。经常遇到这种情况:文件名明明是 .log,用 cat 打开一堆乱码——其实它是 logrotate 轮转之后 gzip 压缩过的旧日志,得用 zcat 或者 gunzip 解开看。
二、查看目录内容
bash
ls -l # 长格式,显示权限、大小、修改时间
ls -la # 加 -a 显示隐藏文件(以 . 开头的文件)
ls -lh # 大小以人类可读格式显示(K、M、G)
ls -ltr # 按修改时间排序,最新在最后看日志目录的时候 ls -lhtr /var/log 这个组合特别顺手——-t 按时间排序、-r 反序(最新的放最后),这样最新产生的日志文件在最下面,一眼就能看到,不用往上翻一长串历史文件。
三、文件内容查看
小文件直接 cat 一次全输出:
bash
cat /etc/hosts大文件用 less,可以前后翻页、搜索,不会像 cat 那样一次性刷屏:
bash
less /var/log/messagesless 里几个高频操作:
| 键 | 干什么 |
|---|---|
/keyword | 向下搜索 |
?keyword | 向上搜索 |
n | 跳到下一个匹配 |
N | 跳到上一个匹配 |
g | 跳到文件开头 |
G | 跳到文件末尾 |
q | 退出 |
看文件头和尾:
bash
head -n 20 app.log # 前 20 行
tail -n 50 app.log # 最后 50 行
tail -f app.log # 持续跟踪新增内容(实时看日志)tail -f 是排查问题时的神器,适合流量不大的日志实时监控。但如果日志刷得飞快(比如高 QPS 的访问日志),直接 tail -f 眼睛根本跟不上,得配合 grep 过滤关键字,或者按时间段把日志切出来再看。
四、复制移动删除
bash
cp source.txt target.txt # 复制文件
cp -a /etc/nginx /backup/nginx # 递归复制,保留权限、时间戳、软链接
mv old.txt new.txt # 移动或重命名
rm file.txt # 删除文件
rm -r dir # 递归删除目录这里要强调一下 cp -a:备份配置目录时用 cp -a 比 cp -r 靠谱得多。-a 会保留属主、权限模式、修改时间、软链接,而 cp -r 默认会丢掉这些。等你恢复配置的时候发现权限全乱了,服务起不来,就知道为什么该用 -a 了。
删除操作没有回收站,rm 完基本找不回来。删之前确认两件事——当前路径对不对、目标对不对:
bash
pwd
ls -ld target-dir变量拼接路径的删除命令是高危操作。如果变量没赋值(为空),rm -rf /$UNDEFINED_VAR/ 展开就是 rm -rf /,整个系统直接没了——这种事故真实发生过。遇到变量拼路径的情况,先 echo 把展开结果打印出来确认,再执行 rm。
五、文件查找
find 是按条件搜索文件的主力工具,支持文件名、大小、时间等多种过滤:
bash
find /etc -name "*.conf" # 按文件名查找
find /var -type f -size +100M # 查找大于 100M 的文件
find /var/log -type f -mtime +7 # 修改时间在 7 天前的文件
find /var/log -type f -mmin -30 # 30 分钟内修改过的文件排查磁盘空间告警,套路基本固定:先用 du 看哪个目录在占空间,再用 find 定位具体大文件:
bash
du -sh /* # 看根目录下各目录的占用
du -sh /var/* # 逐层深入,定位到 /var 下哪个子目录
find /var -type f -size +1G -ls # 直接列出大于 1G 的文件找到大文件之后,先确认这个文件还在不在被进程写入,再决定怎么清理。如果某个进程还持有这个文件的句柄(比如 Nginx 还在往 access.log 写),直接 rm 删掉,磁盘空间不会立即释放——文件从目录里消失了,但 inode 还在,因为进程还占着。这时候要么重启那个进程,要么用 truncate 把文件清空而不是删掉。
六、软链接和硬链接
软链接(符号链接)接近 Windows 快捷方式的概念——它是一个特殊文件,里面记录的是另一个文件的路径。目标文件不存在时,软链接就成了"断链",访问会报 No such file。
bash
ln -s /opt/app/releases/v1.2.3 /opt/app/current
ls -l /opt/app/current # 输出里会显示 -> 指向的路径软链接最典型的用法是版本切换。发布新版本时,把 current 指向新版本目录,要回滚就指回旧版本目录,应用代码一直读 /opt/app/current 这个路径,完全感知不到背后换了版本:
bash
ln -sfn /opt/app/releases/v1.2.4 /opt/app/current这几个参数的意思:-s 创建软链接、-f 强制覆盖已有链接、-n 关键——它确保当 current 已经是个指向目录的链接时,ln 是替换这个链接本身,而不是钻进目录内部操作。没加 -n 是个经典坑。
硬链接就不一样了,它和目标文件指向同一个 inode(磁盘上存文件元数据和数据位置的结构)。同一个 inode 可以有多个文件名,删掉其中一个,只要还有别的文件名指向这个 inode,数据就还在。
bash
ln app.log app.log.link
ls -li app.log app.log.link # 第一列 inode 号相同硬链接运维里很少手动建,但它背后的原理跟一个常见问题直接相关:日志文件被 rm 删了,磁盘空间却没释放。原因就是进程还持有这个文件的文件描述符,inode 的引用计数没归零,空间没真正释放。lsof | grep deleted 能看到这种情况——列出哪些"已删除"的文件还被进程占着。
七、文件时间戳
每个文件其实有三个时间,不是一个。stat 命令能一次看全:
bash
stat app.log| 时间 | 含义 | 什么时候变 |
|---|---|---|
| Access(atime) | 最后访问时间 | 读取文件内容时更新 |
| Modify(mtime) | 最后修改时间 | 修改文件内容时更新 |
| Change(ctime) | 最后状态变更时间 | 改内容、改权限、改属主等元数据时都更新 |
排查"配置改了为什么没生效"的时候,stat 比 ls -l 更有用——它能同时看到三个时间,还能看到 inode 号。有时候你以为改的是 A 文件,服务读的其实是另一个路径下的同名文件,或者是个软链接指向了别处。通过 inode 号对比,能确认"我改的这个文件"和"服务实际加载的那个文件"是不是同一个。