通常情况下,Linux默认的最大文件描述符数目是1024,对于通常的程序来说1024应当是足够使用的(Nginx、系统进程等)。并且像mysql、java等单进程处理大量恳求的应拿来说就未必了。假如单个进程打开的文件描述符数目超过了系统定义的值,都会提及“toomanyfilesopen”的错误提示。
假如想查看当前进程打开了多少个文件,可以执行如下命令查看:
lsof-n|awk'{print$2}'|sort|uniq-c|sort-nr|more
执行后可以看见,第一列是打开的文件描述符数目,第二列是进程id。
限制级别
最大文件描述符数的限制可以分为3种:
shell级别的限制
假如在shell中执行ulimit-n4096后,表示将当前用户所有进程能打开的最大文件数目设置为4096.但只是在当前shell中有效,退出后再登陆则又恢复成之前的限制。
用户级别的限制
用户级别的限制是针对具体的用户,一个用户可以通过多个shell打开,这儿不针对每一个shell限制。
系统级别的限制
这一级别的限制是对整个系统的所有用户的限制,可以执行cat/proc/sys/fs/file-max来查看。
ulimit命令ulimit功能介绍
考虑一下如下情况:
一台Linux主机上同时通过ssh登陆了20个人,假如在系统资源无限制的情况下,这20个人同时打开了100个文档,但是每位文档的大小大约有20M,这时系统的显存资源都会力不从心了。
ulimit用于限制shell启动进程所占用的资源,支持以下各种类型的限制:所创建的内核文件的大小、进程数据块的大小、shell进程创建文件的大小、内存锁住的大小、常驻显存集的大小、打开文件描述符的数目、分配堆栈的最大大小、CPU时间、单个用户的最大线程数、shell进程所能使用的最大虚拟显存。同时,它支持对资源的硬限制和软限制。
ulimit可以作用于用户登入的当前shell会话,是一种临时限制。在会话中止时便结束限制,在shell中执行该命令不会影响其他shell会话。
假如想要使限制永久生效,则须要设置/etc/security/limits.conf文件,这个文件稍后会提到。
ulimit的使用说明
执行helpulimit命令可以查看一下该命令的使用说明:
ulimit限制最大打开文件描述符个数
由上可知linux基础教程,假如要限制最大打开文件描述符的个数可以执行以下命令:
ulimit-n1000
该命令表示将最大打开文件描述符的个数限制为1000(只在当前shell中有效)。
这儿须要注意的地方是,linux资源限制的形式可分为软限制和硬限制。
从ulimit的使用说明来看,ulimit的参数早已包含了软限制和硬限制,-H代表硬限制,-S代表软限制。
比如,执行ulimit-Hn1000表示将硬限制设置为1000,同样ulimit-Sn1000表示将软限制设置为1000,倘若不指定-H或是-S,则相当于把软限制和硬限制都设置为1000。
它们之间的关系是:
下边通过几个反例来说明ulimit命令的使用。
ulimit-n的使用
假如你没有配置过,则默认的限制为1024
12
[root@localhost ~]# ulimit -n1024
将限制设置为2048
1
[root@localhost ~]# ulimit -n 2048
查看软限制和硬限制
1234
[root@localhost ~]# ulimit -Sn2048[root@localhost ~]# ulimit -Hn2048
对于root用户,可以将降低硬限制
12
[root@localhost ~]# ulimit -n 2049[root@localhost ~]#
对于普通用户,通过ulimit-n来查看
12
[sangjian@localhost ~]$ ulimit -n1024
将限制改为1023,执行成功
12
[sangjian@localhost ~]$ ulimit -n 1023[sangjian@localhost ~]$
将限制改为1025,执行失败
12
[sangjian@localhost ~]$ ulimit -n 1025-bash: ulimit: open files: 无法修改 limit 值: 不允许的操作
可见suse linux 下载,普通用户只能缩小限制,而不能扩大限制。
刚刚说到执行ulimit-n是同时对软限制和硬限制都生效的,如今将软限制改为1000,执行成功
12
[sangjian@localhost ~]$ ulimit -Sn 1000[sangjian@localhost ~]$
将软限制改为1024linux 文件描述符,执行失败,由于硬限制的值为1023
12
[sangjian@localhost ~]$ ulimit -Sn 1024-bash: ulimit: open files: 无法修改 limit 值: 无效的参数
更改最大文件限制数目的方法/etc/security/limits.conf
limits.conf文件实际是LinuxPAM(插入式认证模块,PluggableAuthenticationModules)中pam_limits.so的配置文件,突破系统的默认限制,对系统访问资源有一定保护作用。limits.conf和sysctl.conf区别在于limits.conf是针对用户,而sysctl.conf是针对整个系统参数配置。
limits.conf的格式如下:
1
username|@groupname type resource limit
username|@groupname:设置须要被限制的用户名,组名后面加@和用户名区别。也可以用转义*来做所有用户的限制。
type:有soft,hard和-,soft指的是当前系统生效的设置值。hard表明系统中所能设定的最大值。soft的限制不能比har限制高。用-就表明同时设置了soft和hard的值。
resource:
123456789101112
core - 限制内核文件的大小date - 最大数据大小fsize - 最大文件大小memlock - 最大锁定内存地址空间nofile - 打开文件的最大数目rss - 最大持久设置大小stack - 最大栈大小cpu - 以分钟为单位的最多 CPU 时间noproc - 进程的最大数目as - 地址空间限制maxlogins - 此用户允许登录的最大数目maxsyslogins - 系统所有登录的最大数量
比如,假如想把最大文件描述符数设置为4096,且对所有用户生效,则在该文件中添加:
12
* soft nofile 4096* hard nofile 4096
/proc/sys/fs/file-max
该文件是系统级别的限制,可以查看该文件:
12
[root@localhost ~]# cat /proc/sys/fs/file-max185983
可以看见,系统级别的最大文件描述符数是185983,该限制是对整个系统的所有用户生效。并且不是就不可以设置更大的限制数目呢?答案是否定的。对于root来说,可以设置小于这个数目的限制,比如:
12
[root@localhost ~]# ulimit -n 185984[root@localhost ~]#
发觉执行成功了,说明root是可以更改为更大的限制数目的。
虽然,/proc/sys/fs/file-max是系统给出的建议值,系统会计算资源给出一个和合理值,通常跟显存有关系,显存越大,改值越大,而且仅仅是一个建议值linux 文件描述符,limits.conf的设定完全可以超过/proc/sys/fs/file-max。通过limits.conf文件来配置也是可以的。
须要注意的地方ulimit-n设置的是当前用户单个进程才能打开的文件描述符个数还是所有进程的文件描述符个数?
对于第一点,网上这两种说法都有,具体我也做了一些试验,比如,当用vim查看一个文件时,通过另一个shell登陆后,查看vim进程的pid:
123
[sangjian@localhost ~]$ ps -ef | grep vimsangjian 6099 6036 0 23:39 pts/0 00:00:00 vim test.shsangjian 6101 5986 0 23:39 pts/3 00:00:00 grep --color=auto vim
可知,pid是6099,查看/proc/6099/fd中的文件:
123456
[sangjian@localhost ~]$ ll /proc/6099/fd总用量 0lrwx------. 1 sangjian sangjian 64 11月 19 23:41 0 -> /dev/pts/0lrwx------. 1 sangjian sangjian 64 11月 19 23:41 1 -> /dev/pts/0lrwx------. 1 sangjian sangjian 64 11月 19 23:39 2 -> /dev/pts/0lrwx------. 1 sangjian sangjian 64 11月 19 23:41 4 -> /home/sangjian/.test.sh.swp
每位进程的信息就会在/proc目录中保存,fd目录为打开的文件描述符,可以看见当前打开了4个文件描述符。
更改/etc/security/limits.conf文件:
12
sangjian soft nofile 20sangjian hard nofile 20
将sangjian这个用户的最大打开文件描述符个数设置为20,由于设置太小的话shell登陆都不成功。之后新开了6个shell以sangjian这个用户来登陆,而且每位都用vim打开一个文件,结果是都可以打开,这也就是说使用ulimit-n限制的是每位进程最大打开文件描述符的数目。
lsof-ppid查看的结果是否都是该进程打开的文件描述符?
不都是。
lsof命令列举的是一个进程及其子进程与什么文件有关联。
请注意:关联文件和打开文件描述符是不同的,关联文件的数目可能远远小于打开的文件描述符的数目。
例如刚才查看的vim命令执行后,在/proc目录下查看了打开的文件描述符是4个,这么我们再通过lsof来看一下:
可以听到,这个数目早已远远小于4了,这是为何呢?
google找了一些资料,大约缘由是lsof会列举系统中所占用的资源,并且这种资源不一定会占用打开的文件描述符(例如共享显存,讯号量,消息队列,显存映射等,尽管占用了这种资源但不占用打开文件号),因而有可能出现cat/proc/sys/fs/file-max的值大于lsof|wc-l。