一、limits.conf原理
工作原理
limits.conf文件实际是Linux PAM(插入式认证模块,Pluggable Authentication Modules)中 pam_limits.so 的配置文件,突破系统的默认限制,对系统访问资源有一定保护作用。 limits.conf 和sysctl.conf区别在于limits.conf是针对用户,而sysctl.conf是针对整个系统参数配置。
limits.conf是pam_limits.so
的配置文件,然后/etc/pam.d/
下的应用程序调用pam_***.so
模块。譬如说,当用户访问服务器,服务程序将请求发送到PAM模块,PAM模块根据服务名称在/etc/pam.d
目录下选择一个对应的服务文件,然后根据服务文件的内容选择具体的PAM模块进行处理。
文件格式
username|@groupname type resource limit
1)username|@groupname
设置需要被限制的用户名,组名前面加@和用户名区别。也可用通配符*来做所有用户的限制
2)type
类型有soft,hard 和 -
- soft 指的是当前系统生效的设置值
- hard 表明系统中所能设定的最大值,soft 的限制不能比 hard 限制高
- - 就表明同时设置了 soft 和 hard 的值
3)resource: 表示要限制的资源
- core - 限制内核文件的大小
- core file : 当一个程序崩溃时,在进程当前工作目录的core文件中复制了该进程的存储图像。core文件仅仅是一个内存映象(同时加上调试信息),主要是用来调试的。core文件是个二进制文件,需要用相应的工具来分析程序崩溃时的内存映像,系统默认core文件的大小为0,所以没有被创建。可以用ulimit命令查看和修改core文件的大小。 #ulimit -c 0 #ulimit -c 1000 #ulimit -c unlimited 注意:如果想让修改永久生效,则需要修改配置文件,如 .bash_profile、/etc/profile或/etc/security/limits.conf
- date - 最大数据大小
- fsize - 最大文件大小
- memlock - 最大锁定内存地址空间
- nofile - 打开文件的最大数目
- 对于需要做许多套接字连接并使它们处于打开状态的应用程序而言,最好通过使用ulimit -n,或者通过设置nofile参数,为用户把文件描述符的数量设置得比默认值高一些
- rss - 最大持久设置大小
- stack - 最大栈大小
- cpu - 以分钟为单位的最多 CPU 时间
- noproc - 进程的最大数目
- as - 地址空间限制
- maxlogins - 此用户允许登录的最大数目
示例
限制admin用户登录到sshd的服务不能超 过2个
echo session required pam_limits.so >> /etc/pam.d/sshd echo admin - maxlogins 2 >> /etc/security/limits.conf
- 查看应用程序能否被PAM支持,用ldd
- 同理limits.conf要使用就必须保证/etc/pam.d/login 中有下面:session required pam_limits.so
设置
- 暂时生效,ulimit 命令
- 永久生效,通过将一个相应的 ulimit 语句添加到由登录 shell 读取的文件之一(例如 ~/.profile),即特定于 shell 的用户资源文件;或者通过编辑 /etc/security/limits.conf
二、ulimit
ulimit 用于限制 shell 启动进程所占用的资源,支持以下各种类型的限制:所创建的内核文件的大小、进程数据块的大小、Shell 进程创建文件的大小、内存锁住的大小、常驻内存集的大小、打开文件描述符的数量、分配堆栈的最大大小、CPU 时间、单个用户的最大线程数、Shell 进程所能使用的最大虚拟内存。同时,它支持硬资源和软资源的限制
作为临时限制,ulimit 可以作用于通过使用其命令登录的 shell 会话,在会话终止时便结束限制,并不影响于其他 shell 会话。而对于长期的固定限制,ulimit 命令语句又可以被添加到由登录 shell 读取的文件中,作用于特定的 shell 用户
- 只对当前tty(终端有效),若要每次都生效的话,可以把ulimit参数放到对应用户的.bash_profile里面
- ulimit命令本身就有分软硬设置,加-H就是硬,加-S就是软
- 默认显示的是软限制,如果运行ulimit命令修改的时候没有加上的话,就是两个参数一起改变生效
ulimit命令用来限制系统用户对shell资源的访问,常用参数解释如下
ulimit(选项) -a:显示目前资源限制的设定; -c <core文件上限>:设定core文件的最大值,单位为区块; -d <数据节区大小>:程序数据节区的最大值,单位为KB; -f <文件大小>:shell所能建立的最大文件,单位为区块; -H:设定资源的硬性限制,也就是管理员所设下的限制; -m <内存大小>:指定可使用内存的上限,单位为KB; -n <文件数目>:指定同一时间最多可开启的文件数; -p <缓冲区大小>:指定管道缓冲区的大小,单位512字节; -s <堆叠大小>:指定堆叠的上限,单位为KB; -S:设定资源的弹性限制; -t <CPU时间>:指定CPU使用时间的上限,单位为秒; -u <程序数目>:用户最多可开启的程序数目; -v <虚拟内存大小>:指定可使用的虚拟内存上限,单位为KB。
Linux是有文件句柄限制的,而且Linux默认不是很高,一般都是1024,生产服务器用其实很容易就达到这个数量
系统的限制文件在 /proc/sys/fs/file-max 、/proc/sys/fs/file-nr中
/proc/sys/fs/file-max
决定了当前内核可以打开的最大的文件句柄数
The value in file-max denotes the maximum number of file handles that the Linux kernel will allocate. When you get a lot of error messages about running out of file handles, you might want to raise this limit. The default value is 10% of RAM in kilobytes. To change it, just write the new number into the file
意思是file-max一般为内存大小(KB)的10%来计算,如果使用shell,可以这样计算
grep -r MemTotal /proc/meminfo | awk ‘{printf("%d",$2/10)}‘
/proc/sys/fs/file-nr
Historically, the three values in file-nr denoted the number of allocated file handles, the number of allocated but unused file handles, and the maximum number of file handles. Linux 2.6 always reports 0 as the number of free file handles -- this is not an error, it just means that the number of allocated file handles exactly matches the number of used file handles.
查找文件句柄问题的时候,还有一个很实用的程序lsof.可以很方便看到某个进程开了那些句柄.也可以看到某个文件/目录被什么进程占用了.
lsof -n |awk ‘{print $2}‘|sort|uniq -c |sort -nr|more
修改完重新登录就可以见到,使用 ulimit -a 查看确认
设置
- 针对所有用户的设置,在/etc/security/limits.conf文件,其是可以对系统用户、组进行cpu、文件数等限制的,通过它可以针对某个用户或全部进行限制。但不能超越系统的限制;
- (*表示所有用户、soft表示可以超出,但只是警告;hard表示绝对不能超出,unlimited用于表示不限制)如果想对所有用户设置,也可以放在/etc/profile文件里面,下面是该文件里面的默认参数:ulimit -S -c 0 > /dev/null 2>&1
修改ulimit最大限制
1)使用命令修改
查询当前终端的文件句柄数: ulimit -n 回车,一般的系统默认的1024.
修改文件句柄数为65535,ulimit -n 65535.此时系统的文件句柄数为65535.
2)将ulimit 值添加到/etc/profile文件中(适用于有root权限登录的系统)
为了每次系统重新启动时,都可以获取更大的ulimit值,将ulimit 加入到/etc/profile 文件底部
echo ulimit -n 65535 >>/etc/profile source /etc/profile ulimit -n
3)OK,好多朋友都以为大功告成了,可以突然发现自己再次登录进来的时候,ulimit的值还是1024,这是为什么呢?
关键的原因是你登录的用户是什么身份,是不是root用户,由于服务器的root用户权限很大,一般是不能用来登录的,都是通过自己本人的登录权限进行登录,并通过sudo方式切换到root用户下进行工作。 用户登录的时候执行sh脚本的顺序:
/etc/profile.d/file /etc/profile /etc/bashrc /home/.admin/.bashrc /home/.admin/.bash_profile
由于ulimit -n的脚本命令加载在第二部分,用户登录时由于权限原因在第二步还不能完成ulimit的修改,所以ulimit的值还是系统默认的1024
解决办法: 修改linux的软硬件限制文件
echo ‘ * soft nproc 11000 * hard nproc 11000 * soft nofile 655350 * hard nofile 655350‘ >> /etc/security/limits.conf
4)经过以上修改,在有些系统中,用一般用户再登陆,仍然没有修改过来,那么需要检查是否有如下文件,如果没有,则要添加如下内容:
echo session required /lib/security/pam_limits.so >> /etc/pam.d/sshd service sshd reload
5)如果仍然不行,那么需要修改如下文件
echo UsePrivilegeSeparation no >> /etc/ssh/sshd_config
ulimit -n and /proc/sys/fs/file-max 有什么区别
1、file-max 是内核级别的,所有的进程总和不能超过这个数
2、ulimit是进程级别的
[email protected]:~$ ulimit -n 1024 [email protected]:~$ lsof | grep me | wc -l 8145 #!/usr/bin/perl $count = 0; @filedescriptors; while ($count <= 1024) { $FILE = ${count}; open $FILE, ">", "/tmp/example$count" or die "\n\n FDs: $count $!"; push(@filedescriptors, $FILE); $count ++; } //FDs: 1021 Too many open files at ./test.pl line 8. //1021 because there were 3 open file descriptors before reaching the while loop (stdout, stdin and stderr)
三、关闭IPV6
目前为止我们还不需要IPv6,系统安装完之后是自带并且开启了的,需要我们关闭
ifconfig | grep inet6 || lsmod | grep ipv6
1、如果出现inet6 addr…的字样,说明就是安装了
2、显示内核加载的ipv6相关模块
通过以下命令禁用
sed -i ‘s/^NETWORKING_IPV6=yes/NETWORKING_IPV6=no/‘ /etc/sysconfig/network echo ‘ alias net-pf-10 off alias ipv6 off ‘ >> /etc/modprobe.d/dist.conf chkconfig ip6tables off
四、sysctl.conf工作原理
sysctl命令被用于在内核运行时动态地修改内核的运行参数,可用的内核参数在目录/proc/sys
中。它包含一些TCP/IP堆栈和虚拟内存系统的高级选项, 这可以让有经验的管理员提高引人注目的系统性能。用sysctl可以读取设置超过五百个系统变量
sysctl.conf设置
这是一个在网络上流传依旧的sysctl.conf优化配置sysctl.conf设置
#禁用包过滤功能 net.ipv4.ip_forward = 0 #启用源路由核查功能 net.ipv4.conf.default.rp_filter = 1 #禁用所有IP源路由 net.ipv4.conf.default.accept_source_route = 0 #使用sysrq组合键是了解系统目前运行情况,为安全起见设为0关闭 kernel.sysrq = 0 #控制core文件的文件名是否添加pid作为扩展 kernel.core_uses_pid = 1 #开启SYN Cookies,当出现SYN等待队列溢出时,启用cookies来处理 net.ipv4.tcp_syncookies = 1 #每个消息队列的大小(单位:字节)限制 kernel.msgmnb = 65536 #整个系统最大消息队列数量限制 kernel.msgmax = 65536 #单个共享内存段的大小(单位:字节)限制,计算公式64G*1024*1024*1024(字节) kernel.shmmax = 68719476736 #所有内存大小(单位:页,1页 = 4Kb),计算公式16G*1024*1024*1024/4KB(页) kernel.shmall = 4294967296 #timewait的数量,默认是180000 net.ipv4.tcp_max_tw_buckets = 6000 #开启有选择的应答 net.ipv4.tcp_sack = 1 #支持更大的TCP窗口. 如果TCP窗口最大超过65535(64K), 必须设置该数值为1 net.ipv4.tcp_window_scaling = 1 #TCP读buffer net.ipv4.tcp_rmem = 4096 131072 1048576 #TCP写buffer net.ipv4.tcp_wmem = 4096 131072 1048576 #为TCP socket预留用于发送缓冲的内存默认值(单位:字节) net.core.wmem_default = 8388608 #为TCP socket预留用于发送缓冲的内存最大值(单位:字节) net.core.wmem_max = 16777216 #为TCP socket预留用于接收缓冲的内存默认值(单位:字节) net.core.rmem_default = 8388608 #为TCP socket预留用于接收缓冲的内存最大值(单位:字节) net.core.rmem_max = 16777216 #每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目 net.core.netdev_max_backlog = 262144 #web应用中listen函数的backlog默认会给我们内核参数的net.core.somaxconn限制到128,而nginx定义的NGX_LISTEN_BACKLOG默认为511,所以有必要调整这个值 net.core.somaxconn = 262144 #系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。这个限制仅仅是为了防止简单的DoS攻击,不能过分依靠它或者人为地减小这个值,更应该增加这个值(如果增加了内存之后) net.ipv4.tcp_max_orphans = 3276800 #记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M内存的系统而言,缺省值是1024,小内存的系统则是128 net.ipv4.tcp_max_syn_backlog = 262144 #时间戳可以避免序列号的卷绕。一个1Gbps的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。这里需要将其关掉 net.ipv4.tcp_timestamps = 0 #为了打开对端的连接,内核需要发送一个SYN并附带一个回应前面一个SYN的ACK。也就是所谓三次握手中的第二次握手。这个设置决定了内核放弃连接之前发送SYN+ACK包的数量 net.ipv4.tcp_synack_retries = 1 #在内核放弃建立连接之前发送SYN包的数量 net.ipv4.tcp_syn_retries = 1 #开启TCP连接中time_wait sockets的快速回收 net.ipv4.tcp_tw_recycle = 1 #开启TCP连接复用功能,允许将time_wait sockets重新用于新的TCP连接(主要针对time_wait连接) net.ipv4.tcp_tw_reuse = 1 #1st低于此值,TCP没有内存压力,2nd进入内存压力阶段,3rdTCP拒绝分配socket(单位:内存页) net.ipv4.tcp_mem = 94500000 915000000 927000000 #如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是60 秒。2.2 内核的通常值是180秒,你可以按这个设置,但要记住的是,即使你的机器是一个轻载的WEB服务器,也有因为大量的死套接字而内存溢出的风险,FIN- WAIT-2的危险性比FIN-WAIT-1要小,因为它最多只能吃掉1.5K内存,但是它们的生存期长些。 net.ipv4.tcp_fin_timeout = 15 #表示当keepalive起用的时候,TCP发送keepalive消息的频度(单位:秒) net.ipv4.tcp_keepalive_time = 30 #对外连接端口范围 net.ipv4.ip_local_port_range = 2048 65000 #表示文件句柄的最大数量 fs.file-max = 102400
这是我在实际生产系统自动化部署中用的配置
net.ipv4.ip_forward = 0 net.ipv4.conf.default.rp_filter = 1 net.ipv4.conf.default.accept_source_route = 0 kernel.sysrq = 0 kernel.core_uses_pid = 1 net.ipv4.tcp_syncookies = 1 kernel.msgmnb = 65536 kernel.msgmax = 65536 kernel.shmmax = 68719476736 kernel.shmall = 4294967296 net.ipv4.tcp_max_tw_buckets = 6000 net.ipv4.tcp_sack = 1 net.ipv4.tcp_window_scaling = 1 net.ipv4.tcp_wmem = 8192 4336600 873200 net.ipv4.tcp_rmem = 32768 4336600 873200 net.core.wmem_default = 8388608 net.core.rmem_default = 8388608 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 net.core.netdev_max_backlog = 262144 net.core.somaxconn = 262144 net.ipv4.tcp_max_orphans = 3276800 net.ipv4.tcp_max_syn_backlog = 262144 net.ipv4.tcp_timestamps = 1 net.ipv4.tcp_synack_retries = 1 net.ipv4.tcp_syn_retries = 1 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_mem = 786432 1048576 1572864 net.ipv4.tcp_fin_timeout = 30 #net.ipv4.tcp_keepalive_time = 30 net.ipv4.tcp_keepalive_time = 300 net.ipv4.ip_local_port_range = 1024 65000
/sbin/sysctl -p最后记得刷新立即生效
http://serverfault.com/questions/122679/how-do-ulimit-n-and-proc-sys-fs-file-max-differ