本文属于原创,转载注明出处,欢迎关注微信小程序
小白AI
或者网站 https://xiaobaiai.net
前言
这篇文章应该是网络上关于ulimit最全的介绍了,有扩展,有打破沙锅追到底。文章尽可能的保证正确性,参考了多篇国外获得多数赞同的文章。文章实际操作内容均在Ubuntu16.04
上测试通过。
术语 | 释义 |
---|---|
File Descriptor | 文件描述符(FD),在Unix和相关的计算机操作系统中,文件描述符(FD,较不常见的fildes)是用于访问文件或其他输入/输出资源的抽象指示符(句柄),例如管道 或网络套接字 。 |
Shell Session | shell会话 |
User Level | 用户级别 |
System Level | 系统级别 |
1 ulimit命令
- ulimit可以限制使用系统资源的范围。是一个内置BASH命令。
- ulimit设置项仅在当前shell作用(类似
export
命令,永久生效可以写入相关配置文件),即Shell Session
级别作用 - 写入
~/.profile或~/.bashrc
只对当前用户持久性生效 - 写入
/etc/security/limits.conf
可针对性配置,系统级持久性生效 - 调整相关硬限制值(
Hard Limit
),设置一次后,以后的值只能小于上一次设置的值 - 如果不加S或H修饰,则默认同时修改
Soft Limit
和Hard Limit
值
$ help limit
Syntax
ulimit [-acdfHlmnpsStuv] [limit]
Key(设置项)
-S Set a soft limit for the given resource(设置软资源限制,设置后可以增加,但是不能超过硬资源设置)
-H Set a hard limit for the given resource(设置硬资源限制,一旦设置不能增加)
-a All current limits are reported(显示当前所有的 limit 信息).
-c The maximum size of core files created(最大的 core 文件的大小, 以 blocks 为单位).
-d The maximum size of a process's data segment(进程最大的数据段的大小,以 Kbytes 为单位).
-f The maximum size of files created by the shell(default option,进程可以创建文件的最大值,以 blocks 为单位)
-l The maximum size that can be locked into memory(最大可加锁内存大小,以 Kbytes 为单位).
-m The maximum resident set size(最大内存大小,以 Kbytes 为单位).
-n The maximum number of open file descriptors(可以打开最大文件描述符的数量).
-p The pipe buffer size(管道缓冲区的大小,以 Kbytes 为单位).
-s The maximum stack size(线程栈大小,以 Kbytes 为单位).
-t The maximum amount of cpu time in seconds(最大的 CPU 占用时间,以秒为单位).
-u The maximum number of processes available to a single user(用户最大可用的进程数).
-v The maximum amount of virtual memory available to the process(进程最大可用的虚拟内存,以 Kbytes 为单位).
注:所有设置blocks均指文件系统的最小分配单位block,典型值将介于1k和4k之间,对于超大型文件系统,最高可达16k及以上。
相关设置示例:
# 示例1:查看所有默认设置项值
$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 7823
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 7823
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
# 示例2:软限制设置core dump文件最大大小为2048
$ ulimit -Sc 51200
# 示例3:core dump文件大小无限制
$ ulimit -c unlimited
# 限制管道缓冲区大小为512Kbytes(KB)
$ ulimit -p 512
# 示例5:查看当前终端进程limits
$ echo $$ | cat /proc/`awk '{print $1}'`/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 8041 8041 processes
Max open files 1024 4096 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 8041 8041 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 40 40
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
2 hard limit 和 soft limit
- 软限制是内核对相应资源强制执行的值,硬限制作为软限制的上限,即软限制值无法超过硬限制的值。
- 如果没有相应的设置权限,如root,只能将其软限制设置为0到硬限制范围内的值,并且(不可逆地)降低其硬限制,即
硬限制值
修改了,后面再修改只能降低不能升高,当然软限制
值只要在硬限制值范围内都是可以修改的。而拥有设置权限的用户可以对任一限制的值进行任意更改。
3 更改默认limit值
3.1 持久性更改
3.1.1 用户级更改
通过配置/etc/security/limits.conf
文件,可以更改ulimit的默认资源限制值。包括对指定用户使用资源的限制配置。
# /etc/security/limits.conf
#
#Each line describes a limit for a user in the form:
#
#<domain> <type> <item> <value>
#
#Where:
#<domain> can be:
# - a user name
# - a group name, with @group syntax
# - the wildcard *, for default entry
# - the wildcard %, can be also used with %group syntax,
# for maxlogin limit
# - NOTE: group and wildcard limits are not applied to root.
# To apply a limit to the root user, <domain> must be
# the literal username root.
#
#<type> can have the two values:
# - "soft" for enforcing the soft limits
# - "hard" for enforcing hard limits
#
#<item> can be one of the following:
# - core - limits the core file size (KB)
# - data - max data size (KB)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
# - nofile - max number of open files
# - rss - max resident set size (KB)
# - stack - max stack size (KB)
# - cpu - max CPU time (MIN)
# - nproc - max number of processes
# - as - address space limit (KB)
# - maxlogins - max number of logins for this user
# - maxsyslogins - max number of logins on the system
# - priority - the priority to run user process with
# - locks - max number of file locks the user can hold
# - sigpending - max number of pending signals
# - msgqueue - max memory used by POSIX message queues (bytes)
# - nice - max nice priority allowed to raise to values: [-20, 19]
# - rtprio - max realtime priority
# - chroot - change root to directory (Debian-specific)
#
#<domain> <type> <item> <value>
#
# examples:
#* soft core 0
#root hard core 100000
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
#ftp - chroot /ftp
#@student - maxlogins 4
# End of file
通过设置domain
来指定生效范围,如可以指定用户名或者组名等。配置项说明如下:
core - 限制内核文件的大小
date - 最大数据大小
fsize - 最大文件大小
memlock - 最大锁定内存地址空间
nofile - 打开文件的最大数目(socket fd也属于文件,因此可以设置该项)
rss - 最大持久设置大小
stack - 最大栈大小
cpu - 以分钟为单位的最多 CPU 时间
noproc - 进程的最大数目
as - 地址空间限制
maxlogins - 此用户允许登录的最大数目
注意修改完limits.conf文件后,需要重启才能生效,通过ulimit -a检验是否生效。
3.1.2 单用户级更改
用户登录的时候执行shell脚本的顺序:
- 我们所使用的基本上都是交互式登陆(
interactive-login
) interactive-login
登陆执行脚本顺序/etc/profile
~/.bash_profile
~/.bashrc
~/.bash_login
/etc/bashrc
~/.profile
non-interactive-login shell
加载环境变量的顺序是~/.bashrc
/etc/bashrc
因此我们可以将ulimit
配置写入到上述相关配置文件中。一般来说profile
是与环境变量相关的配置,如PATH
,而bashrc
与shell相关的配置。
3.2 临时性更改
直接在终端中执行ulimit
,则就是临时性更改,类似export命令
。
3.3 系统级更改
file-max
是可以在整个系统(内核)中打开的最大文件数。这是在内核级别强制执行的。该值可以临时调整,无需重启生效,示例:
# 方式一
echo 100000 > /proc/sys/fs/file-max
# 方式二
$ vim /etc/sysctl.conf
fs.file-max = 100000
$ sysctl -p
# 方式三
$ sysctl -w fs.file-max = 100000
4 ulimit的应用
大多数类UNIX操作系统(包括Linux和macOS)提供了在每个进程和每个用户的基础上限制和控制系统资源(如线程,文件和网络连接)使用的方法。这些“ulimits”阻止单个用户使用太多系统资源。有时,这些限制具有较低的默认值,这可能会导致正常操作过程中出现许多问题,因此需要另外重新设置。
红帽企业版Linux、CentOS 6及Ubuntu默认最大进程限制为1024,core dump文件大小限制为0blocks。
4.1 ulimit与core dump文件
首先需要设置好/etc/security/limits.conf
* soft core 2048
* hard core 2048
测试用例hello.c:
#include <stdio.h>
int main()
{
char *str = "hello, core dump!";
str[0] = 0;
return 0;
}
$ gcc hello.c -o hello
$ ./hello
Segmentation fault (core dumped)
# 在当前可执行文件目录下生成了core文件,如果没有可以去/var/crash/目录下查找
或者在硬限制的范围内在终端通过ulimit
临时修改软限制的值:
# 查看当前core是否开启,0未开启,大于0表示core文件最大blocks大小
$ ulimit -c
# 设置core文件最大blocks大小
$ ulimit -c {num}
注:1. 如果出现
ulimit core file size cannot modify limit operation not permitted
错误提示,就是你设置的值超过了硬限制值,需要检查下。如果core
文件没有生成,再次检查/etc/security/limits.conf
是否设置对了。2. 如果配置好了,还是没有生成core文件,可能原因就是配置的blocks大小比生成的core要小,所以无法生成。
gdb调试core文件:
# gdb -c core文件名 程序名称
$ gdb -c {your_core_filename} {process_name}
# 然后输入bt查看 dump 堆栈信息
其他配置:
/proc/sys/kernel/core_uses_pid
可以控制core文件的文件名中是否添加pid作为扩展,0不加,1则加。- 指定core文件生成路径命名方式
$ cat /proc/sys/kernel/core_pattern
查看得到的结果是|/usr/share/apport/apport %p %s %c %P
,开头的|
表示,core文件会交给apport程序去处理,而apport会将core dump文件保存在/var/crash
目录下$ sudo vim /etc/sysctl.conf
kernel.core_pattern=/var/crash/%E.%p.%t.%s
E代表路径,p指进程pid,t指时间戳,s指哪个信号让程序崩溃了,配置生成路径为/var/crash
$ sudo sysctl -p
让修改了sysctl.conf立即生效
4.2 ulimit与网络连接数
首先我们要知道几个含义:
file-max
是可以在整个系统(内核)中打开的最大文件数。这是在内核级别强制执行的。cat /proc/sys/fs/file-max
可以查看sysctl fs.file-nr
最后一项就是file-max
lsof
: 在没有任何选项的情况下,lsof列出属于所有活动进程的所有打开文件。lsof | wc -l
计算所有活动进程打开的文件数目,这个值是小于等于file-max
ulimit
是用于在用户级别强制执行的资源限制,比如某个用户某个进程(shell)所能打开的文件句柄个数lsof -u {username} | wc -l
获取指定用户当前打开的文件个数lsof -u root | wc -l
获取root用户当前打开的文件个数lsof -p {pid} | wc -l
获取指定pid所打开的文件个数ls -1 /proc/{pid}/fd | wc -l
获取被该pid打开的文件个数,但是相比lsof包含更多其他句柄,如epoll
或inotify
句柄。(参考)
修改网络连接数即修改open files
参数数值:
#/etc/security/limits.conf
* hard nofile 20000
或者在硬限制的范围内在终端通过ulimit
临时修改软限制的值。
# 查看当前shell当前用户打开文件个数限制
$ ulimit -n
# 设置
$ ulimit -n {num}
测试:
- 在一个shell终端中设置
ulimit -n 512
,在该shell终端打开服务端,等该客户端连接 - 在另一个shell终端中设置
ulimit -n 1024
,开始不断创建socket连接- 当达到512个连接时(包含服务端shell终端所有打开的描述符个数),提示
Network Error
之类信息
- 当达到512个连接时(包含服务端shell终端所有打开的描述符个数),提示
其他扩展:
- 查看端口限制范围
$ sysctl -a | grep port_range
或$ cat /proc/sys/net/ipv4/ip_local_port_range
- 增加可用端口范围
$ sudo vim /etc/sysctl.conf
net.ipv4.ip_local_port_range = {min_num} {max_num}
min_num为端口起始范围,max_num为端口终止范围sudo sysctl -p
立即生效
5 参考
- https://ss64.com/bash/ulimit.html
- https://linux.die.net/man/5/limits.conf
- https://linux.xiao5tech.com/linux/advance/linux_optimize_ulimit_error.html
- http://www.361way.com/linux-core-dump/3830.html
- https://docs.mongodb.com/manual/reference/ulimit/
- http://senlinzhan.github.io/2017/12/31/coredump/
- https://www.kernel.org/doc/Documentation/sysctl/fs.txt
- http://linux-sxs.org/bedtime/bs_login.html
- https://en.wikipedia.org/wiki/File_descriptor
- https://superuser.com/questions/789448/choosing-between-bashrc-profile-bash-profile-etc
- https://unix.stackexchange.com/questions/38175/difference-between-login-shell-and-non-login-shell
- https://www.cyberciti.biz/tips/linux-procfs-file-descriptors.html