【Linux】如何获取打开文件和文件描述符数量

linux 的文件描述符

文件描述符(FD:file descriptors),也可以说是文件句柄,当某个程序打开文件时,内核返回相应的文件描述符,程序为了处理该文件必须引用此描述符。文件描述符是一个正整数,用以标明每一个被进程所打开的文件和 socket。最前面的三个文件描述符(0,1,2)分别与标准输入(stdin),标准输出(stdout)和标准错误(stderr)对应,后面打开的文件依此类推对应 3、4…… 。

linux 系统对每个用户、进程、或整个系统的可打开文件描述符数量都有一个限制,一般默认为 1024。当我们在系统或应用的日志中碰到“too many open files”错误记录时,这个其实不是说打开的文件过多,而是打开的文件描述符数量已达到了限制,这时就需要增加文件描述符的数量限制了。

获取系统打开的文件描述符数量

1
2
[root@localhost ~]# cat /proc/sys/fs/file-nr
1216 0 197787
  • 第一列 1216 :为已分配的 FD 数量
  • 第二列 0 :为已分配但尚未使用的 FD 数量
  • 第三列 197787 :为系统可用的最大 FD 数量

已用 FD 数量=为已分配的 FD 数量 - 为已分配但尚未使用的 FD 数量。注意,这些数值是系统层面的。

获取进程打开的文件描述符数量

1
2
3
4
5
6
7
[root@localhost ~]# pidof vim
3253
[root@localhost ~]# ll /proc/3253/fd
lrwx------. 1 test test 64 6月 8 18:11 0 -> /dev/pts/0
lrwx------. 1 test test 64 6月 8 18:11 1 -> /dev/pts/0
lrwx------. 1 test test 64 6月 8 18:11 2 -> /dev/pts/0
lrwx------. 1 test test 64 6月 8 18:11 4 -> /home/test/.bash_history.swp

可以看到 vim 进程用了 4 个 FD

更改文件描述符限制

当碰到“too many open files”错误时,就需要增加文件描述符的限制数量,系统的默认文件描述符都比较大,一般来说,只需增加用户或进程的就可以了

用户或进程

1
2
3
4
5
[root@localhost ~]# ulimit -n
1024
[root@localhost ~]# ulimit -n 10240
[root@localhost ~]# ulimit -n
10240

注意,使用 ulimit 命令更改后只是在当前会话生效,当退出当前会话重新登录后又会回到默认值 1024,要永久更改可以修改文件 /etc/security/limit.conf,如

1
[root@localhost ~]#vi /etc/security/limits.conf

加入 “abc hard nofile 10240”

  • abc:用户名,即允许 test 使用 ulimit 命令更改 FD 限制,最大值不超过 10240,更改后 abc 用户的每一个进程(以 abc 用户运行的进程)可打开的 FD 数量为 10240 个

  • hard:限制类型,有 soft/hard 两种,达到 soft 限制会在系统的日志(一般为/var/log/messages)里面记录一条告警日志,但不影响使用。hard,达到这个限制,有日志且会影响使用。

  • nofile:限制的内容,nofile - max number of open files

  • 1024 :值

更改后,退出终端重新登录,用 ulimit 看看有没有生效,如果没生效,可以在 abc 用户的.bash_profile 文件加上 ulimit -n 10240 ,以使用户 abc 每次登录时都会将 FD 最大值更改为 10240,如:

1
2
3
4
5
[root@localhost ~]#echo "ulimit -n 10240" >> /home/abc/ .bash_profile
10240
[root@localhost ~]# su - abc
[abc@localhost ~]\$ ulimit -n
10240

limit.conf 文件里面本身已有很详细的使用方法,这个下次可以说说。

系统级别

将整个操作系统可以使用的 FD 数量更改为 51200

1
2
3
[root@localhost ~]# echo "51200" > /proc/sys/fs/file-max
[root@localhost ~]# cat /proc/sys/fs/file-nr
1184 0 51200

像这样更改在系统重启后会恢复到默认值,要永久更改可以在 sysctl.conf 文件加上 fs.file-max = 51200

如:

1
[root@localhost ~]# echo "fs.file-max = 51200" >> /etc/sysctl.conf

获取打开的文件数量

linux 的一切皆为文件,那么如何知道系统/应用打开了哪些或是多少个文件呢?很简单,用 lsof 命令就行了,lsof,list open files 的简写,可列出程序或系统正在使用的文件。

获取整个系统打开的文件数量

1
2
[root@localhost ~]# lsof |wc -l
1864

获取某个用户打开的文件数量

1
2
[root@localhost ~]# lsof -u test |wc -l
15

获取某个程序打开的文件数量

1
2
3
4
[root@localhost ~]# pidof vim
3253
[root@localhost ~]# lsof -p 3253 |wc -l
31

上面所示只是用 lsof 来显示已打开的文件数量,lsof 的功能远不止这些,有兴趣可以 man lsof 看一下

指标 测试值
测试时长 12 小时 15 分
数据量 108000000
平均消费速率(TPS) 6500 条/秒
总结 在这种高峰数据量的情况下,mthinkingdata 会堵塞一部分流量,除非优化利用 Redis 的机制,使服务支持多个 Redis 实例存储