• 排查file-max limit 65536 reached错误


    近期遇到服务器宕机,重启后排查系统日志,看到/var/log/messages中在宕机前出现大量file-max limit 65536 reached错误:

    报file-max limit reached,说明机器上文件句柄的使用量超过了设定值,以下是排查过程的整理。先说怎么看文件句柄数,这个数据记在/proc/sys/fs/file-nr中:

    图中1056表示当前已打开文件句柄数量,65536表示最大数量。最大值由/proc/sys/fs/file-max控制,可以通过echo 100000 > /proc/sys/fs/file-max来修改。由于出现宕机前新部署了应用,因此怀疑与它有关,通过不断刷新,发现此应用运行时确实导致文件句柄上升,一段时间后上升至6000多。在linux下很多操作都会占用文件句柄,比如打开文件、打开目录、socket、pipe、共享内存等,首先怀疑有文件open后没有close,用lsof查下:

    可以看到数量很少,排查系统内其它进程,lsof -n | awk '{print $2}' | sort | uniq -c | sort -nr | head,看到没有哪个进程占用大量文件,那多出的5000多个句柄应该不是文件,往共享内存方向排查,用pmap看看进程是否有mmap相关操作:

    5392,这下对上了,用pmap进一步分析,发现有大量config.dat存在:

    找到开发排查源码,发现对此文件的使用涉及了mmap操作,先open文件,然后用mmap把文件映射到内存,再close文件,结果用完后没有munmap操作,导致文件句柄不断上涨。

    问题定位了,翻回来看为什么文件close了依然会导致文件句柄上涨。每个打开的文件都会有一个句柄用于描述文件属性,进程中用一个整数型的文件描述符指向具体的句柄。由于linux内核中对文件描述符是使用引用计数管理,mmap后,引用计数+1,此时尽管close了文件描述符,但引用计数不为0,内核不会回收文件句柄。

    写个小程序验证一下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    
    int main()
    {
        int i;
        for(i = 0;i < 1000;++i)
        {
            int fd;
            char * addr;
            fd = open("/dev/zero", O_RDONLY);        //打开文件
            if(!fd)
                exit(1);
    
            addr = mmap(NULL, 4096, PROT_READ, MAP_PRIVATE, fd, 0);        //映射
            //munmap(addr, 4096);                    //此行不执行就会导致句柄上涨
            close(fd);                                //关闭文件
        }
    
        pause();
    }

    重复1000次,每次open和close是匹配的,但mmap没有munmap,执行后的效果:

    和预期一致,加上munmap后,对比测试则不会再出现这1000个句柄占用。

  • 相关阅读:
    uva11572 Unique Snowflakes
    codeforces#333 div2 B. Approximating a Constant Range
    uva11134 Fabled Rooks
    吐槽。。。
    uva 1605 Building for UN
    uva 120 Stacks of Flapjacks
    uva1152 4 Values whose Sum is 0
    uva817 According to Bartjens
    uva11214 Guarding the Chessboard
    无标题
  • 原文地址:https://www.cnblogs.com/BoyTNT/p/15011207.html
Copyright © 2020-2023  润新知