本文屬於原創,轉載註明出處,歡迎關注微信小程序
小白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