寫在前面
我遇到了什么問題:
- 很老的一個系統bug原因升級,大概五六年沒有重啟機器了,4A平臺上面通過ssh遠程連接linux機器,偶爾連接不上
- 即使連接之后命令無法正常執行,執行了沒有反應。
- 即使可以執行,執行命名報-bash: fork: retry: Resource temporarily unavailable.(資源暫時不可用)
出現問題的原因是什么:
Linux進程數超過了設置的最大進程數。會對系統進行資源限制,所以分配給ssh進程的資源時有時無,一些命令的bash進程會被殺調,以保證系統進程不超過設置的最大進程數,無法正常執行。即下面的第一個輸出要遠遠小與第二個和第三個輸出。如果有些接近就會出現這種問題
┌──[[email protected]]-[/]
└─$ ps -eLf | wc -l # 當前進程數
221
┌──[[email protected]]-[/]
└─$ ulimit -u # 用戶的最大進程數
15665
┌──[[email protected]]-[/]
└─$ sysctl kernel.pid_max # 內核設置的最大進程數
kernel.pid_max = 150000
┌──[[email protected]]-[/]
└─$
我是怎樣解決的
修改內核參數,調整最大進程數限制。這里修改的話需要root權限,同時需要修改兩個地方。
其一:用戶登錄會加載pam_limit模塊,pam_limit模塊讀取配置文件 /etc/security/limits.conf來限制用戶資源的占用。可以使用ulimit的命令來查看和臨時設置資源信息,也可以通過 寫入/etc/security/limits.conf來永久配置,配置文件在每次登錄時會加載。可以用來設置ssh連接數,最大進程數等。
其二:Linux系統中內核kernel模塊,有個全局的設置最大進程數的內核參數,需要修改這個參數,內核參數的設置方式有臨時設置和永久設置兩種方式,臨時設置完就會刷新,重啟失效。可以先臨時設置后查看效果,然后永久設置。
人生當苦無妨,良人當歸即好.——烽火戲諸侯《雪中悍刀行》
查看當前用戶的活躍進程數
┌──[[email protected]]-[/]
└─$ ps -eLf | wc -l # 當前進程數
221
查看用戶允許運行的最大進程數
┌──[[email protected]]-[~]
└─$ 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) 15665
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) 15665
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited # 無限大
┌──[[email protected]]-[~]
└─$
ulimit為shell內建指令,可用來控制shell執行程序的資源。
語法:
ulimit [-aHS][-c <core文件上限>][-d <數據節區大小>][-f <文件大小>][-m <內存大小>][-n <文件數目>][-p <緩沖區大小>][-s <堆棧大小>][-t <CPU時間>][-u <程序數目>][-v <虛擬內存大小>]
參數: |
– |
-a |
顯示目前資源限制的設定。 |
-c |
<core文件上限> 設定core文件的最大值,單位為區塊。 |
-d |
<數據節區大小> 程序數據節區的最大值,單位為KB。 |
-f |
<文件大小> shell所能建立的最大文件,單位為區塊。 |
-H |
設定資源的硬性限制,也就是管理員所設下的限制。 |
-m |
<內存大小> 指定可使用內存的上限,單位為KB。 |
-n |
<文件數目> 指定同一時間最多可開啟的文件數。 |
-p |
<緩沖區大小> 指定管道緩沖區的大小,單位512字節。 |
-s |
<堆棧大小> 指定堆棧的上限,單位為KB。 |
-S |
設定資源的彈性限制。 |
-t |
<CPU時間> 指定CPU使用時間的上限,單位為秒。 |
-u |
<進程數目> 用戶最多可開啟的進程數目。 |
-v |
<虛擬內存大小> 指定可使用的虛擬內存上限,單位為KB。 |
┌──[[email protected]]-[~]
└─$ ulimit -u
15665
默認值
用戶 |
描述 |
root 賬號 |
ulimit -u的值 默認是 |
普通賬號 |
ulimit -u的值 默認是 |
修改用戶允許運行的最大進程數
臨時修改
┌──[[email protected]]-[~]
└─$ ulimit -u 75535
┌──[[email protected]]-[~]
└─$ ulimit -u
75535
┌──[[email protected]]-[~]
└─$
永久修改
在/etc/security/limits.conf 文件里添加如下內容
* soft nproc 65535
* hard nproc 65535
關鍵字 |
描述 |
nproc |
是操作系統級別對每個用戶創建的進程數的限制 |
nofile |
是每個進程可以打開的文件數的限制 |
soft xxx |
代表警告的設定,可以超過這個設定值,但是超過后會有警告。 |
hard xxx |
代表嚴格的設定,不允許超過這個設定的值。 |
┌──[[email protected]]-[~]
└─$ echo "* soft nproc 65535" >> /etc/security/limits.conf
┌──[[email protected]]-[~]
└─$ echo "* hard nproc 65535" >> /etc/security/limits.conf
┌──[[email protected]]-[~]
└─$ cat /etc/security/limits.conf | grep nproc
# - nproc - max number of processes
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
* soft nproc 65535
* hard nproc 65535
┌──[[email protected]]-[~]
└─$
從新通過ssh的方式登錄,就會刷新 ulimit -u的值
查看Linux內核模塊kernel允許的最大進程數
查看kernel.pid_max的內核參數
┌──[[email protected]]-[~]
└─$ sysctl -a | grep pid_max #查看pid的內核參數
kernel.pid_max = 131072
sysctl: reading key "net.ipv6.conf.all.stable_secret"
sysctl: reading key "net.ipv6.conf.br-0e0cdf9c70b0.stable_secret"
sysctl: reading key "net.ipv6.conf.br-4b3da203747c.stable_secret"
sysctl: reading key "net.ipv6.conf.default.stable_secret"
sysctl: reading key "net.ipv6.conf.Docker0.stable_secret"
sysctl: reading key "net.ipv6.conf.ens32.stable_secret"
sysctl: reading key "net.ipv6.conf.lo.stable_secret"
┌──[[email protected]]-[/]
└─$ sysctl kernel.pid_max
kernel.pid_max = 131072
根據變量找到對應的內核參數文件位置
┌──[[email protected]]-[~]
└─$ cd /proc/sys/kernel/;cat pid_max
131072
調整kernel.pid_max內核參數
臨時調整內核參數
┌──[[email protected]]-[/proc/sys/kernel]
└─$ echo 150000 > pid_max
┌──[[email protected]]-[/proc/sys/kernel]
└─$ cat pid_max # 臨時調整內核參數
150000
永久調整kernel.pid_max內核參數
┌──[[email protected]]-[/]
└─$ echo "kernel.pid_max = 150000" >> /etc/sysctl.conf # 永久調整
┌──[[email protected]]-[/]
└─$ cat /etc/sysctl.conf | grep kernel
kernel.pid_max = 150000
┌──[[email protected]]-[/]
└─$ sysctl -p
net.ipv4.ip_forward = 1
vm.swAppiness = 20
kernel.pid_max = 150000
┌──[[email protected]]-[/]
└─$