limit資源限制ulimit 詳解
系統性能一直是一個受關注的話題,如何通過最簡單的設定來實現最有效的效能調優,如何在有限資源的條件下保證程式的運作,ulimit 是我們在處理這些問題時,經常使用的一種簡單手段。ulimit 是一種 Linux 系統的內鍵功能,它具有一套引數集,用於為由它生成的 shell程序及其子程序的資源使用設定限制。
命令總結:
檢視系統使用者所有限制值:ulimit -a
設定使用者open files(使用者可以開啟檔案的最大數目):ulimit -n 4096。執行該命令非root使用者只能設定到4096。想要設定到8192需要sudo許可權或者root使用者。
檢視當前系統開啟的檔案數量:
檢視當前程序的開啟檔案數量:lsof -p pid | wc -l (lsof -p 1234 | wc -l )
檢視當前程序的最大可以開啟的檔案數:cat /proc/PID/limits (如果通過ulimit -n 設定或者修改/etc/security/limits.conf,看看程序是否生效)
檢視系統總限制開啟檔案的最大數量:cat /proc/sys/fs/file-max
lsof只能以root許可權執行。在終端下輸入lsof即可顯示系統開啟的檔案,因為 lsof 需要訪問核心記憶體和各種檔案,所以必須以 root 使用者的身份執行它才能夠充分地發揮其功能。
1、ulimit的功能
假設有這樣一種情況,當一臺 linux 主機上同時登陸了 10 個人,在系統資源無限制的情況下,這 10 個使用者同時打開了 500 個文件,而假設每個文件的大小有 10M,這時系統的記憶體資源就會受到巨大的挑戰。
而實際應用的環境要比這種假設複雜的多,例如在一個嵌入式開發環境中,各方面的資源都是非常緊缺的,對於開啟檔案描述符的數量,分配堆疊的大小,CPU 時間,虛擬記憶體大小等等,都有非常嚴格的要求。資源的合理限制和分配,不僅僅是保證系統可用性的必要條件,也與系統上軟體執行的效能有著密不可分的聯絡。這時,ulimit 可以起到很大的作用,它是一種簡單並且有效的實現資源限制的方式。
ulimit 用於限制 shell 啟動程序所佔用的資源,支援以下各種型別的限制:
所建立的核心檔案的大小、
程序資料塊的大小、
Shell 程序建立檔案的大小、
記憶體鎖住的大小、
常駐記憶體集的大小、
開啟檔案描述符的數量、
分配堆疊的最大大小、
CPU 時間、
單個使用者的最大執行緒數、
Shell 程序所能使用的最大虛擬記憶體。同時,它支援硬資源和軟資源的限制。
作為臨時限制,ulimit 可以作用於通過使用其命令登入的 shell 會話,在會話終止時便結束限制,並不影響於其他 shell 會話。而對於長期的固定限制,ulimit 命令語句又可以被新增到由登入 shell 讀取的檔案中,作用於特定的 shell 使用者。
2、使用ulimit
ulimit 通過一些引數選項來管理不同種類的系統資源。
ulimit 命令的格式為:ulimit [options] [limit]
主要關注兩個:
1)open files:– 使用者可以開啟檔案的最大數目
對應ulimit 的命令ulimit -n,可以使用ulimit -n 臨時設定。
對應/etc/security/limits.conf的資源限制類型是:nofile
* soft nofile 4096
* hard nofile 4096
2)max user processes – 使用者可以開啟程序/執行緒的最大數目
對應ulimit 的命令ulimit -u 臨時修改max user processes的值:ulimit -u 8192。
對應/etc/security/limits.conf的資源限制類型是: noproc
* soft nproc 8192
具體的 options 含義以及簡單示例可以參考以下表格。
ulimit 引數說明
選項 含義
-a 顯示當前系統所有的limit資源資訊。
-H 設定硬資源限制,一旦設定不能增加。例如:ulimit – Hs 64;限制硬資源,執行緒棧大小為 64K。
-S 設定軟資源限制,設定後可以增加,但是不能超過硬資源設定。例如:ulimit – Sn 32;限制軟資源,32 個檔案描述符。
-c 最大的core檔案的大小,以 blocks 為單位。例如:ulimit – c unlimited; 對生成的 core 檔案的大小不進行限制。
-f 程序可以建立檔案的最大值,以blocks 為單位.例如:ulimit – f 2048;限制程序可以建立的最大檔案大小為 2048 blocks。
-d 程序最大的資料段的大小,以Kbytes 為單位。例如:ulimit -d unlimited;對程序的資料段大小不進行限制。
-m 最大記憶體大小,以Kbytes為單位。例如:ulimit – m unlimited;對最大記憶體不進行限制。
-n 可以開啟的最大檔案描述符的數量。例如:ulimit – n 128;限制最大可以使用 128 個檔案描述符
-s 執行緒棧大小,以Kbytes為單位。例如:ulimit – s 512;限制執行緒棧的大小為 512 Kbytes。
-p 管道緩衝區的大小,以Kbytes 為單位。例如ulimit – p 512;限制管道緩衝區的大小為 512 Kbytes。
-u 使用者最大可用的程序數。例如 limit – u 65536;限制使用者最多可以使用 65536個程序。
-v 程序最大可用的虛擬記憶體,以Kbytes 為單位。ulimit – v 200000;限制最大可用的虛擬記憶體為 200000 Kbytes。
-t 最大CPU佔用時間,以秒為單位。ulimit – t unlimited;對最大的 CPU 佔用時間不進行限制。
-l 最大可加鎖記憶體大小,以Kbytes 為單位。
我們可以通過以下幾種方式來使用 ulimit:
一、在使用者的啟動指令碼中
如果使用者使用的是 bash,就可以在使用者的目錄下的 .bashrc 檔案中,加入 ulimit – u 64,來限制使用者最多可以使用 64 個程序。此外,可以在與 .bashrc 功能相當的啟動指令碼中加入 ulimt。
二、在應用程式的啟動指令碼中
如果使用者要對某個應用程式 myapp 進行限制,可以寫一個簡單的指令碼 startmyapp。
ulimit – s 512
myapp
以後只要通過指令碼 startmyapp 來啟動應用程式,就可以限制應用程式 myapp 的執行緒棧大小為 512K。
三、直接在控制檯輸入
ulimit – p 256
限制管道的緩衝區為 256K。
四、修改所有 linux 使用者的環境變數檔案:
vi /etc/profile
ulimit -u 10000
ulimit -n 4096
ulimit -d unlimited
ulimit -m unlimited
ulimit -s unlimited
ulimit -t unlimited
ulimit -v unlimited
儲存後執行#source /etc/profile 使其生效
四、也可以針對單個使用者的.bash_profile設定:
vi ~./.bash_profile
#ulimit -n 1024
重新登陸ok
3、使用者程序的有效範圍
ulimit 作為對資源使用限制的一種工作,是有其作用範圍的。那麼,它限制的物件是單個使用者,單個程序,還是整個系統呢?事實上,ulimit 限制的是當前 shell 程序以及其派生的子程序。舉例來說,如果使用者同時運行了兩個 shell 終端程序,只在其中一個環境中執行了 ulimit – s 100,則該 shell 程序裡建立檔案的大小收到相應的限制,而同時另一個 shell終端包括其上執行的子程式都不會受其影響:
Shell 程序 1
ulimit –s 100
cat testFile > newFile
File size limit exceeded
Shell 程序 2
cat testFile > newFile
ls –s newFile
323669 newFile
針對使用者永久生效:
那麼,是否有針對某個具體使用者的資源加以限制的方法呢?答案是有的,方法是通過修改系統的 /etc/security/limits.conf配置檔案。該檔案不僅能限制指定使用者的資源使用,還能限制指定組的資源使用。該檔案的每一行都是對限定的一個描述。
limits.conf的格式如下:
<domain> <type> <item> <value>
username|@groupname type resource limit
domain:username|@groupname:設定需要被限制的使用者名稱,組名前面加@和使用者名稱區別。也可以用萬用字元*來做所有使用者的限制。
type:有 soft,hard 和 -,soft 指的是當前系統生效的設定值。hard 表明系統中所能設定的最大值。soft 的最大值不能超過hard的值。用 – 就表明同時設定了 soft 和 hard 的值。
resource:
core – 限制核心檔案的大小
date – 最大資料大小
fsize – 最大檔案大小
memlock – 最大鎖定記憶體地址空間
nofile – 開啟檔案的最大數目
rss – 最大持久設定大小
stack – 最大棧大小
cpu – 以分鐘為單位的最多 CPU 時間
noproc – 程序的最大數目(系統的最大程序數)
as – 地址空間限制
maxlogins – 此使用者允許登入的最大數目
要使 limits.conf 檔案配置生效,必須要確保 pam_limits.so 檔案被加入到啟動檔案中。
檢視 /etc/pam.d/login 檔案中有:
session required /lib/security/pam_limits.so
例如:解除 Linux 系統的最大程序數和最大檔案開啟數限制:
vi /etc/security/limits.conf
# 新增如下的行
* soft noproc 20000 #軟連線
* hard noproc 20000 #硬連線
* soft nofile 4096
* hard nofile 4096
說明:* 代表針對所有使用者,noproc 是代表最大程序數,nofile 是代表最大檔案開啟數
需要注意一點:/etc/security/limits.d下也有noproc最大進引數的限制:
即 /etc/security/limits.d/下的檔案覆蓋了/etc/security/limits.conf設定的值
這個是官網答疑:https://access.redhat.com/solutions/406663
# /etc/security/limits.conf
#This file sets the resource limits for the users logged in via PAM.
#It does not affect resource limits of the system services.
#Also note that configuration files in /etc/security/limits.d directory,
#That means for example that setting a limit for wildcard domain here
[[email protected] ~]# cat /etc/security/limits.d/20-nproc.conf
# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.
* soft nproc 8192
root soft nproc unlimited
現在已經可以對程序和使用者分別做資源限制了,看似已經足夠了,其實不然。很多應用需要對整個系統的資源使用做一個總的限制,這時候我們需要修改 /proc 下的配置檔案。/proc 目錄下包含了很多系統當前狀態的引數,例如 /proc/sys/kernel/pid_max,/proc/sys/net/ipv4/ip_local_port_range 等等,從檔案的名字大致可以猜出所限制的資源種類。
注意:
通過讀取/proc/sys/fs/file-nr可以看到當前使用的檔案描述符總數。另外,對於檔案描述符的配置,需要注意以下幾點:
-
所有程序開啟的檔案描述符數不能超過/proc/sys/fs/file-max
-
單個程序開啟的檔案描述符數不能超過user limit中nofile的soft limit
-
nofile的soft limit不能超過其hard limit
-
nofile的hard limit不能超過/proc/sys/fs/nr_open
4、使用者程序的有效範圍
問題1:su切換使用者時提示:Resource temporarily unavailable
或者通過程序跟蹤 strace -p pid 看到:Resource temporarily unavailab
通過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) 63463
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 65535
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) 4096
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
在上面這些引數中,通常我們關注得比較多:
open files: 一個程序可開啟的最大檔案數.
max user processes: 系統允許建立的最大程序數量.
通過 ps -efL|grep java |wc -l
#24001
這個得到的執行緒數竟然是2萬多,遠遠超過4096
我們可以使用 ulimit -u 20000 修改max user processes的值,但是隻能在當前終端的這個session裡面生效,重新登入後仍然是使用系統預設值。
正確的修改方式是修改/etc/security/limits.d/20-nproc.conf檔案中的值。先看一下這個檔案包含什麼:
$ cat /etc/security/limits.d/90-nproc.conf
# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.
* soft nproc 8192
我們只要修改上面檔案中的8192這個值,即可。
問題2:linux 開啟檔案數 too many open files 解決方法
在執行某些命令或者 tomcat等伺服器持續執行 一段時間後可能遇到 too many open files。
出現這句提示的原因是程式開啟的檔案/socket連線數量超過系統設定值。
java程序如果遇到java.net.SocketException: Too many open files,接著可能導致域名解析ava.net.UnknownHostException:
原因是使用者程序無法開啟系統檔案了。
檢視每個使用者最大允許開啟檔案數量
ulimit -a
其中 open files (-n) 65535 表示每個使用者最大允許開啟的檔案數量是65535 。 預設是1024。1024很容易不夠用。
永久修改open files 方法
vim /etc/security/limits.conf
在最後加入
* soft nofile 65535
* hard nofile 65535
或者只加入
* - nofile 65535
最前的 * 表示所有使用者,可根據需要設定某一使用者,例如
fdipzone soft nofile 8192
fdipzone hard nofile 8192
注意"nofile"項有兩個可能的限制措施。就是項下的hard和soft。 要使修改過得最大開啟檔案數生效,必須對這兩種限制進行設定。 如果使用"-"字元設定, 則hard和soft設定會同時被設定。
改完後登出一下就能生效。
通過 ulimit -n或者ulimit -a
檢視系統的最大檔案開啟數已經生效了。但此時檢視程序的最大檔案開啟數沒有變,原因是這個值是在程序啟動的時候設定的,要生效必須重啟!
ok,那就重啟吧,重啟完畢,結果發現依然沒變!這奇了怪了,後來經過好久的排查,最終確認問題是,該程式是通過 supervisord
來管理的,也就是這程序都是 supervisord
的子程序,而 supervisord
的最大檔案開啟數還是老的配置,此時必須重啟 supervisord
才可以。
當大家遇到limits修改不生效的時候,請查一下程序是否只是子程序,如果是,那就要把父程序也一併重啟才可以。