使用 lsof 命令
可以使用 命令查看特定进程打开的文件详情,帮助你找出哪些文件或连接没有被正确关闭
- 列出所有打开的文件
lsof
- 查找特定文件的打开情况:
lsof /path/to/your/file
- 查找特定进程打开的文件:
lsof -p <PID>
- 查找特定用户打开的文件:
lsof -u <username>
- 查找特定命令打开的文件:
lsof -c <command>
命令输出示例和每列代表的信息
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rsyslogd 488 syslog 1w REG 8,1 1151 268940 /var/log/syslog
- COMMAND:打开文件的命令或进程名称。
- PID:进程的进程标识符(PID)。
- USER:启动进程的用户。
- FD:文件描述符,表示文件在进程中的引用。常见值包括: cwd:当前工作目录 txt:程序代码 mem:内存映射文件
NUMBER:实际的文件描述符编号,后面的字符表示文件的打开模式(r 读,w 写,u 读写)。 - TYPE:文件类型,例如: REG:常规文件。
- DIR:目录 FIFO:先进先出队列 CHR:字符设备。
- DEVICE:文件所在的设备。 SIZE/OFF:文件大小或偏移量。
- NODE:文件的节点号。 NAME:文件的名称或路径。
查找打开最多且未被关闭的文件
- 运行 lsof 命令并保存输出:
lsof -p 1234 > /tmp/lsof_output.txt
- 分析输出: 你可以使用 awk 或其他工具来统计每个文件的打开次数。例如:
awk '{print $9}' /tmp/lsof_output.txt | sort | uniq -c | sort -nr
这将输出每个文件被打开的次数,按降序排列。例如:
3 /dev/null
1 /home/user
1 /bin/bash
1 /lib/x86_64-linux-gnu/libtinfo.so.6.1
在这个示例中,/dev/null 文件被打开了 3 次,其他文件各被打开了一次。你可以根据这个信息找出打开最多且未被关闭的文件。
使用watch监控进程打开的文件个数
watch -n 1 "lsof -p <PID> | wc -l"
其中, 是你要监视的进程的进程ID。这个命令会每秒刷新一次,显示该进程当前打开的文件数。
使用“Ctrl + C”退出watch
可能解决的方案
- 增加系统允许的最大文件数:
你可以使用 ulimit 命令来增加当前会话的最大文件数。例如:
ulimit -n 2048
这种方法在重启后会恢复默认值。如果需要永久修改,可以编辑 /etc/security/limits.conf 文件,添加如下内容:
* soft nofile 4096
* hard nofile 4096
- 调整系统文件最大数目
- 要检查系统范围内的打开文件限制
cat /proc/sys/fs/file-max
- 如果需要增加此限制,可以在 /etc/sysctl.conf 文件中添加以下行
fs.file-max = 100000
- 使用以下命令应用新设置:
sudo sysctl -p
两个有用的debug脚本
- watchOpenFileSta.sh
#!/bin/bash
pid=$`
lsof -p $pid > "/tmp/lsof_$pid_output.txt"
lsof -p 1234 > /tmp/lsof_output.txt
- 总结文件打开的情况
#!/bin/bash
# Loop through all the provided files
for file in "$@"
do
# Get the absolute path of the file
absPath=$(realpath "$file")
# Get the file name
fileName=$(basename "$file")
# Remove the file extension
name="${fileName%.*}"
# Get the current time in the format YYYYMMDD_HHMMSS
currTime=$(date +"%Y%m%d_%H%M%S")
# Use awk to extract the 9th column, sort, count unique values, and save the result to a timestamped file
awk '{print $9}' "$absPath" | sort | uniq -c | sort -nr | tee "/tmp/fileOpenState_${name}_${currTime}.txt"
done