京东6.18大促主会场领京享红包更优惠

 找回密码
 立即注册

QQ登录

只需一步,快速开始

linux too many open files 错误处理

2026-6-4 11:20| 发布者: zhaojun917| 查看: 6| 评论: 0

摘要: 查看系统最大文件打开数# cat /proc/sys/fs/file-max65536查看系统当前文件打开数# cat /proc/sys/fs/file-nr2680 0 65536查看系统占用文件打开数前20位# lsof|awk '{print $2}' |sort |uniq -c|sort -nr |head -20 ...
查看系统最大文件打开数
 [root@dzsw_test ~]# cat /proc/sys/fs/file-max 
65536
查看系统当前文件打开数
[root@dzsw_test ~]# cat /proc/sys/fs/file-nr
2680  0  65536

查看系统占用文件打开数前20位
[root@dzsw_test ~]# lsof|awk '{print $2}' |sort |uniq -c|sort -nr |head -20
    145 4766
    102 5310
     71 3318
     69 5100
     69 5049
     69 5006
     69 4968
     69 4933
     69 4921
     69 4905
     69 4849
     69 4806
     69 4750
     67 4699
     67 4698
     67 4697
     67 4673
     67 3330
     65 4657
     65 4632

 查看指定进程占用的fd    
[root@dzsw_test ~]# ls -l /proc/4766/fd |wc -l
417
[root@dzsw_test ~]# ls -l /proc/4766/fd
总用量 277


--单用户最大文件 数
vi   /etc/security/limits.conf
--系统最大文件 数
vi /etc/security/limits.conf

--让配置生效
sysctl -p

*/10 * * * * /root/clearfilenode/auto_kill_top_fd.sh 

*/10 * * * * /root/clearfilenode/clear_deleted_fd.sh


lsof   |grep '(deleted)'

lsof | grep '/tmp/sh-thd-'|grep '(deleted)'|awk '{print $2}' | sort -u|xargs kill -15



你要的是:监控整个系统的全局文件句柄余量,当系统整体快不够用时,自动杀掉占用文件句柄最多的前 N 个进程,而不是判断单个进程。
这是 ** 更安全、更符合你报错(too many open files)** 的脚本!
我现在直接给你写 最终版、可直接上线、带日志、带白名单、自动杀 TopN 的脚本。
全自动系统文件句柄耗尽保护脚本
功能说明
读取系统全局最大句柄 fs.file-max
读取当前系统已使用句柄数
计算使用率,超过阈值(默认 90%)就触发清理
自动找出占用句柄最多的前 3 个进程
白名单进程(sshd/nginx/mysql 等)绝对不杀
完整日志记录
可配置阈值、杀几个、白名单
脚本代码:auto_kill_top_fd.sh



#!/bin/bash

# ====================== 可配置参数 ======================
# 系统文件句柄使用率阈值(超过这个百分比就开始杀进程)
USAGE_LIMIT=90

# 杀掉占用最多的前 N 个进程
KILL_TOP_N=3

# 白名单进程(绝对不杀,用 | 分隔)
WHITE_LIST="sshd|nginx|mysql|redis|dockerd|systemd|bash|crond|syslog"

# 日志文件
LOG="/var/log/auto_kill_top_fd.log"
# =======================================================

# 获取时间
now() {
    date "+%Y-%m-%d %H:%M:%S"
}

echo "================================================" >> $LOG
echo "[$(now)] 开始检查系统全局文件句柄使用率" >> $LOG

# 获取系统最大文件句柄
FILE_MAX=$(cat /proc/sys/fs/file-max)

# 获取已使用句柄(第一列)
FILE_NOW=$(cat /proc/sys/fs/file-nr | awk '{print $1}')

# 计算使用率百分比
USAGE=$(( FILE_NOW * 100 / FILE_MAX ))

echo "[$(now)] 系统最大句柄:$FILE_MAX" >> $LOG
echo "[$(now)] 系统已用句柄:$FILE_NOW" >> $LOG
echo "[$(now)] 当前使用率  :$USAGE%" >> $LOG

# 判断是否超过阈值
if [ $USAGE -lt $USAGE_LIMIT ]; then
    echo "[$(now)] 使用率正常,无需处理" >> $LOG
    exit 0
fi

# ============== 超过阈值,开始查杀 ==============
echo "[$(now)] 使用率超过 ${USAGE_LIMIT}%,开始清理占用最多的进程!" >> $LOG

# 取出所有进程的 FD 数量,排序,取前 N 个,排除白名单
ls /proc | grep -E '^[0-9]+$' | sort -n | while read pid; do
    # 跳过无效PID
    [ ! -d /proc/$pid/fd ] && continue

    # 进程名
    pname=$(ps -p $pid -o comm= 2>/dev/null)
    [ -z "$pname" ] && continue

    # 白名单过滤
    echo "$pname" | grep -qE "^($WHITE_LIST)$" && continue

    # 统计FD数量
    fd=$(ls /proc/$pid/fd 2>/dev/null | wc -l)
    echo "$fd $pid $pname"
done | sort -nr | head -n $KILL_TOP_N | while read fd pid pname; do
    echo "[$(now)] 清理进程:PID=$pid 名称=$pname FD=$fd" >> $LOG
    kill -9 $pid
    echo "[$(now)] 已杀死:$pid" >> $LOG
done

echo "[$(now)] 清理完成!" >> $LOG




批量清空所有 deleted 占用日志脚本(不杀进程、批量释放 fd)
原理:筛选 lsof 标记 (deleted) 的常规文件,批量 > 路径 截断释放句柄,跳过管道、socket、设备文件。
文件名:clear_deleted_fd.sh


#!/bin/bash
# 批量清空被进程占用但已删除的日志,释放fd
LOG_FILE="/root/clearfilenode/clear_deleted.log"
DATE=$(date +"%Y-%m-%d %H:%M:%S")

echo "====================[$DATE]开始清理deleted占用文件====================" >>$LOG_FILE

# 遍历所有deleted普通文件(排除socket、pipe、anon等非磁盘文件)
lsof | grep '/tmp/sh-thd-'|grep '(deleted)'|awk '{gsub(/\(deleted\)$/,"");print $NF}' | sort -u | while read file_path
do
    if [ -n "$file_path" ];then
        echo "清理文件: $file_path" >>$LOG_FILE
        # 截断文件释放句柄
        > "$file_path"
    fi
done

echo "[$DATE]清理完成" >>$LOG_FILE
 
 
lsof | grep '/tmp/sh-thd-'|grep '(deleted)'|awk '{print $2}' | sort -u|xargs kill -15

使用步骤
保存赋权
bash
chmod +x /root/clearfilenode/clear_deleted_fd.sh
手动执行
bash
/root/clearfilenode/clear_deleted_fd.sh
可选定时(建议每 2 小时跑一次)
cron
0 */2 * * * /root/clearfilenode/clear_deleted_fd.sh >/dev/null 2>&1
配套核查命令(执行前后对比 fd)
bash
# 清理前查看deleted数量
lsof|grep deleted|wc -l
# 清理完再查一遍
lsof|grep deleted|wc -l
注意事项
> 文件 只清空内容、不删除文件,业务无报错;
脚本只处理磁盘普通日志,不会操作 socket / 管道等系统 fd,安全;
该脚本治标,长期必须搭配之前 logrotate 日志切割。
需要我顺便加上:清理前输出对应 PID + 进程名到日志吗?

QQ|手机版|小黑屋|梦想之都-俊月星空 ( 粤ICP备18056059号 )|网站地图

GMT+8, 2026-6-5 02:15 , Processed in 0.033593 second(s), 17 queries .

Powered by Mxzdjyxk! X3.5

© 2001-2026 Discuz! Team.

返回顶部