字数 3685,阅读大约需 19 分钟
在 Linux 服务器运维的日常中,“资源被占用”是最让人头疼的问题之一。想卸载数据盘,终端弹出 device is busy;想重启 Nginx,提示 address already in use;想删除日志文件,却被告知“文件正在被使用”。此时,你不需要逐个排查进程,也不用翻遍日志,fuser 就是解决这类问题的“瑞士军刀”。

作为 Linux 内置的进程定位工具,fuser 最大的优势在于反向追踪——它能通过文件、目录、挂载点或网络端口,精准找出所有正在使用它们的进程,甚至能直接执行清理操作。本文整合了基础原理、参数详解与实战场景,摒弃晦涩的官方术语,用一线运维的视角,带你彻底吃透 fuser,解决90%的“占用类”排障问题。
fuser 的全称可以理解为 File User(文件使用者),它的核心逻辑是“以资源为中心,找进程”,这与我们常用的 ps(以进程为中心,找资源)恰好相反。
在Linux 中,fuser 属于 psmisc 工具包,系统默认预装,无需手动安装。它的核心能力可分为三大类,覆盖运维全场景:
/data)的进程,解决“无法卸载”问题;与同类工具(如 lsof)相比,fuser 的优势是轻量、高效、命令简洁,尤其适合快速排障和脚本自动化场景。
在深入参数之前,先掌握 fuser 的最基础用法,建立核心认知。
语法:fuser [资源路径/端口]
# 查看 /root/test.sh 被哪些进程占用
fuser /root/test.sh
# 查看 8080 TCP 端口被哪些进程占用
fuser 8080/tcp典型输出:
/root/test.sh: 12345e 12346f输出结果分为两部分,缺一不可:
fuser 用单个字母标识进程的访问方式,默认只显示核心类型,完整类型如下(按使用频率排序):
举个例子:如果输出是 12345c,说明 PID 为 12345 的进程,当前工作目录就是你查询的目录,此时删除该目录一定会失败。
fuser 的参数不多,但每个都直击运维痛点。我们按“查询”“清理”“特殊场景”分类,结合实际用途讲解,避免孤立记参数。
这类参数用于优化查询结果,是排障的基础,优先掌握。
作用:以类似 ps 的格式输出,显示 PID、用户、进程命令、访问类型,一目了然。
语法:fuser -v [资源]
fuser -v /data/logs输出示例:
USER PID ACCESS COMMAND
/data/logs: root 1234 ..c.. bash
nginx 5678 ..f.. nginx优势:相比最简用法,能直接看到“谁在占用(USER)”“用什么程序占用(COMMAND)”,无需再用 ps -p PID 二次查询。
作用:在 PID 后追加用户名,快速定位“责任人”。
语法:fuser -u [资源]
fuser -u 80/tcp输出示例:
80/tcp: 1234(root) 5678(nginx)提示:如果同时使用 -v,-u 会被自动包含,无需重复添加。
作用:查询指定挂载点或分区上的所有占用进程,而非单个文件/目录。
语法:fuser -v -m [挂载点/块设备]
# 查看 /mnt/data 挂载点的所有占用进程
fuser -v -m /mnt/data
# 也可以直接指定块设备(如 /dev/sdb1)
fuser -v -m /dev/sdb1关键注意:使用 -m 时,fuser 会匹配整个文件系统,而非单个目录。比如查询 /mnt/data/test,会自动识别为 /mnt/data 整个挂载点,这是解决“无法卸载”的核心参数。
作用:明确查询的资源类型,支持 file(文件,默认)、tcp、udp。
语法:fuser -v -n [命名空间] [资源]
# 查 TCP 80 端口(完整写法)
fuser -v -n tcp 80
# 查 UDP 53 端口(完整写法)
fuser -v -n udp 53简化写法(运维通用):直接用 端口/协议,省略 -n,更高效:
fuser -v 80/tcp
fuser -v 53/udp作用:仅查询 IPv4 或 IPv6 端口,避免混淆。
语法:fuser -v -4 [端口/协议] / fuser -v -6 [端口/协议]
# 仅查 IPv4 的 8080 TCP 端口
fuser -v -4 8080/tcp
# 仅查 IPv6 的 8080 TCP 端口
fuser -v -6 8080/tcp这类参数用于终止占用进程,释放资源,属于高危操作,生产环境必须谨慎使用。
作用:向占用进程发送信号,默认发送 SIGKILL(9号信号,强制杀死)。
语法:fuser -k [资源]
# 强制杀死占用 8080 TCP 端口的进程
fuser -k 8080/tcp警告:默认的 9 号信号会强制终止进程,可能导致数据丢失(如正在写入的数据库进程),生产环境优先用“优雅信号”。
作用:替代默认的 SIGKILL,使用指定信号终止进程,常用信号有两种:
语法:fuser -k -[信号名/数字] [资源]
# 优雅杀死占用 /data 的进程(15号信号)
fuser -k -15 /data
# 用信号名写法,更易读
fuser -k -TERM /data
# 重启占用 80/tcp 的 Nginx 进程(1号信号)
fuser -k -HUP 80/tcp作用:杀死进程前,会逐一询问是否确认,避免误杀核心进程(如 systemd、sshd)。
语法:fuser -k -i [资源]
# 确认后杀死占用 /mnt/data 的进程
fuser -k -i -m /mnt/data输出示例:
/mnt/data: 1234 5678
Kill process 1234 (bash)? (y/N)作用:只终止对资源有“写入权限”的进程,保留只读进程,适合需要保留服务的场景。
语法:fuser -k -w [资源]
# 仅杀死写入 /var/log/messages 的进程,保留只读查看的进程
fuser -k -w /var/log/messages作用:不输出任何内容,仅通过返回值判断资源是否被占用(0=被占用,非0=空闲)。
语法:fuser -s [资源]
# 脚本中判断 80 端口是否空闲
if fuser -s 80/tcp; then
echo "80端口已被占用"
else
echo "80端口空闲,启动Nginx"
fi作用:查询可用的杀死信号,避免记混数字,适合新手。
语法:fuser -l
作用:确认 fuser 版本,排查工具兼容性问题。
语法:fuser -V
理论参数最终要落地到场景,以下是 Linux 运维中最常见的 5 个场景,按“问题-排查-解决”的流程,给出可直接复制的命令。
问题:执行 umount /mnt/data 时,提示 umount: /mnt/data: target is busy,无法卸载。
排查思路:找出占用该挂载点的所有进程,确认是否为核心进程,再清理。
操作步骤:
# 第一步:详细查看挂载点占用情况(必做,确认进程是否重要)
sudo fuser -v -m /mnt/data
# 第二步:优雅清理占用进程,加交互确认(生产环境)
sudo fuser -k -i -15 -m /mnt/data
# 第三步:再次尝试卸载
sudo umount /mnt/data
# 若仍无法卸载,强制杀死(最后手段)
sudo fuser -k -i -9 -m /mnt/data
sudo umount /mnt/data问题:启动 SpringBoot 服务时,提示 Address already in use,占用端口为 8080。
排查思路:定位 8080 端口的占用进程,确认是残留进程还是其他服务,再清理。
操作步骤:
# 第一步:查看 8080 TCP 端口的详细占用情况
sudo fuser -v 8080/tcp
# 第二步:若为残留进程,优雅清理
sudo fuser -k -15 8080/tcp
# 第三步:启动服务
java -jar app.jar问题:执行 rm -rf nginx.log 时,删除失败,或删除后磁盘空间未释放(因为进程还在写入)。
排查思路:找出写入该日志的进程,重启进程让其切换日志,再删除。
操作步骤:
# 第一步:查看日志文件的占用进程(重点看 F 类型,即写入进程)
sudo fuser -v nginx.log
# 第二步:向 Nginx 发送重启信号,让其切换日志(不终止服务)
sudo fuser -k -HUP $(cat /var/run/nginx.pid)
# 或直接用 fuser 重启(如果只有一个 Nginx 进程占用)
sudo fuser -k -HUP nginx.log
# 第三步:此时日志文件已无进程写入,可安全删除
rm -rf nginx.log需求:编写定时备份脚本,备份前判断 /dev/sdb1 是否被挂载(是否被占用),空闲才执行备份。
脚本实现:
#!/bin/bash
# 备份脚本:backup.sh
MOUNT_POINT="/mnt/backup"
DEVICE="/dev/sdb1"
# 第一步:静默判断设备是否被占用
if fuser -s $DEVICE; then
echo "$(date +%F_%T):设备 $DEVICE 正在被占用,备份终止" >> /var/log/backup.log
exit 1
fi
# 第二步:设备空闲,挂载并执行备份
sudo mount $DEVICE $MOUNT_POINT
sudo cp -r /data/backup/* $MOUNT_POINT/
echo "$(date +%F_%T):备份完成" >> /var/log/backup.log
# 第三步:卸载设备
sudo umount $MOUNT_POINT需求:测试环境重启时,需要清理 80、443、8080、8090 四个 TCP 端口的残留进程,一键清场。
脚本实现:
#!/bin/bash
# 端口清理脚本:clean_ports.sh
PORTS=(80 443 8080 8090)
PROTOCOL="tcp"
for PORT in "${PORTS[@]}"; do
echo "正在清理 ${PORT}/${PROTOCOL} 端口..."
# 先查看,再交互优雅清理
sudo fuser -v ${PORT}/${PROTOCOL}
sudo fuser -k -i -15 ${PORT}/${PROTOCOL}
done
echo "端口清理完成!"fuser 虽好用,但使用不当可能导致服务中断、数据丢失,以下是一线运维总结的 5 个核心避坑点,必须牢记:
sudo。比如普通用户查 80 端口,会返回空,并非端口空闲,而是权限不够。-15(SIGTERM)优雅退出,只有进程卡死时,才用 -9(SIGKILL)强制杀死。-m,会误杀整个分区的进程。比如 fuser -k -m /root/test,会杀死所有占用 / 分区的进程,直接导致服务器宕机!-v 查询时,若看到 COMMAND 列为 kernel,说明是内核进程占用(如磁盘缓存),fuser 无法杀死,也不要尝试杀死。53/tcp(DNS 服务)还是 53/udp(DNS 解析),否则会查询不到。为了方便日常使用,将核心命令按场景整理为速查清单,可直接复制到服务器的 ~/.bashrc 中,或保存为 fuser_cheat.sh 备用。
# 1. 详细查看文件/目录占用
sudo fuser -v /path/to/file_or_dir
# 2. 详细查看挂载点/分区占用
sudo fuser -v -m /mnt/data
# 3. 详细查看 TCP/UDP 端口占用
sudo fuser -v 80/tcp
sudo fuser -v 53/udp
# 4. 仅查看 IPv4 端口占用
sudo fuser -v -4 8080/tcp
# 5. 查看进程访问类型(含只读/读写)
sudo fuser -v -u /path/to/file# 1. 优雅杀死进程 + 交互确认(生产首选)
sudo fuser -k -i -15 /path/to/file_or_dir
# 2. 清理挂载点占用(卸载前)
sudo fuser -k -i -15 -m /mnt/data
# 3. 释放端口占用(优雅)
sudo fuser -k -i -15 8080/tcp
# 4. 强制杀死卡死进程(最后手段)
sudo fuser -k -i -9 /path/to/file_or_dir# 1. 判断资源是否被占用
if fuser -s 80/tcp; then echo "端口被占用"; else echo "端口空闲"; fi
# 2. 批量清理端口
for port in 80 443 8080; do sudo fuser -k -i -15 ${port}/tcp; donefuser 是 Linux 运维中“小而美”的工具,它不追求复杂的功能,却能精准解决“资源被占用”的核心痛点。掌握它的关键,在于理解“资源→进程”的反向逻辑,熟记访问类型字母,以及坚持“先查询、再确认、后清理”的运维原则。
无论是日常排障、脚本自动化,还是应急处理,这份指南覆盖了从基础到实战的所有内容,建议收藏备用,让 fuser 成为你运维工作中的“得力助手”。