Skip to content

文件管理

日常运维中大量时间在跟文件打交道:查看内容、查找位置、确认类型和权限、清理空间。

一、文件类型

ls -l 第一列的第一个字符标记了文件类型。Linux 里的"文件"不只是普通文本——目录、设备、管道、socket 都以文件的形式存在。

bash
ls -l /etc/passwd /etc /dev/null
标记类型说明
-普通文件文本、二进制、压缩包等等
d目录目录本身也是一个文件,记录包含的文件名和 inode
l软链接指向另一个路径的快捷方式
c字符设备按字符流读写的设备,如终端、串口
b块设备按数据块读写的设备,如硬盘
ssocket进程间通信用的套接字文件
p管道命名管道,用于进程间数据传输

file 命令可以进一步查看文件的真实内容类型:

bash
file /bin/ls           # ELF 可执行文件
file /etc/passwd        # ASCII 文本
file app.log            # 可能是文本、压缩包,或者编码不对的二进制

排查日志打不开时,先用 file 确认一下实际类型。有时候文件后缀名和内容对不上,比如 .log 文件其实是 gzip 压缩过的旧日志。

二、查看目录

bash
ls -l      # 长格式,显示权限、大小、修改时间
ls -la     # 加 -a 显示隐藏文件(以 . 开头的文件)
ls -lh     # 大小以人类可读格式显示(K、M、G)
ls -ltr    # 按修改时间排序,最新在最后

日常看日志目录时 ls -lhtr /var/log 比较顺手,最新的文件在最后面,不用往上翻。

三、查看文件内容

小文件直接 cat 输出全部内容:

bash
cat /etc/hosts

大文件用 less,可以前后翻页搜索:

bash
less /var/log/messages

less 里的常用操作:

功能
/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 适合低流量的日志实时监控。如果日志刷得很快,直接 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 -r 可靠——它会保留属主、权限模式、修改时间和软链接,恢复配置时少很多权限问题。

删除操作没有回收站,rm 之后数据很难恢复。删除前确认当前路径和目标:

bash
pwd
ls -ld target-dir

涉及变量拼接路径时尤其要小心。如果变量为空,rm -rf /$UNDEFINED_VAR/ 的效果等同于 rm -rf /。遇到不确定的情况,先 echo 变量展开的结果,再执行。

五、查找文件

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 分钟内有修改

排查磁盘空间告警时,通常先找到哪些目录在占用空间,再定位具体大文件:

bash
du -sh /*                  # 看根目录下各目录的占用
du -sh /var/*              # 逐层深入
find /var -type f -size +1G -ls    # 直接列出大于 1G 的文件

du 看目录级别占用,find 定位具体文件。找到大文件后,确认文件是否还在被进程写入再决定清理方式——进程持有文件句柄时,rm 不会立即释放磁盘空间。

六、软链接和硬链接

软链接(符号链接)接近 Windows 快捷方式的概念:一个指向另一个文件路径的特殊文件。目标文件不存在时,软链接会变成"断链"。

bash
ln -s /opt/app/releases/v1.2.3 /opt/app/current
ls -l /opt/app/current     # 输出中会显示 -> 指向的路径

版本切换是软链接的典型用法。发布新版本时,把 current 指向新的版本目录,回滚时指回旧目录:

bash
ln -sfn /opt/app/releases/v1.2.4 /opt/app/current

-s 创建软链接,-f 强制覆盖已有链接,-n 确保当目标是已有目录链接时不会钻进目录内部。

硬链接指向同一个 inode(磁盘上存储文件元数据和数据位置的结构)。同一个 inode 可以有多个文件名,删除其中一个,inode 仍然存在。

bash
ln app.log app.log.link
ls -li app.log app.log.link     # 第一列 inode 号相同

硬链接在运维中不常手动创建,但背后的原理和日常一个问题有关:日志文件被 rm 删除后磁盘空间没有释放。这是因为进程仍然持有文件的文件描述符,inode 没有被释放。lsof | grep deleted 可以看到这种情况。

七、文件时间戳

每个文件有三个时间戳:

bash
stat app.log
时间含义触发条件
Access(atime)最后访问时间读取文件内容
Modify(mtime)最后修改时间修改文件内容
Change(ctime)最后状态变更时间修改内容、权限、所有者等元数据

排查配置是否生效时,statls -l 更有用——它能同时看到三个时间,而且能确认 inode 号。有时候修改了一个软链接指向的文件,但服务加载的可能是另一个硬链接或另一个路径下的同名文件。