天天看點

Linux 打開檔案數1024限制的原理以及解決辦法

/proc/sys/fs/file-max 

該檔案指定了可以配置設定的檔案句柄的最大數目。

檢視最大值:

1

2

3

<code>[root@localhost home]</code><code># cat /proc/sys/fs/file-max </code>

<code>100977</code>

<code>[root@localhost home]</code><code>#</code>

這表明這台Linux系統最多允許同時打開(即包含所有使用者打開檔案數總和)100977個檔案,是Linux系統級硬限制,所有使用者級的打開檔案數限制都不應超過這個數值。通常這個系統級硬限制是Linux系統在啟動時根據系統硬體資源狀況計算出來的最佳的最大同時打開檔案數限制,如果沒有特殊需要,不應該修改此限制,除非想為使用者級打開檔案數限制設定超過此限制的值。這個參數的預設值是跟記憶體大小有關系的,增加實體記憶體以後重新開機機器,這個值會增大。大約1G記憶體10萬個句柄的線性關系。

修改值:

如果使用者得到的錯誤消息聲明,類似”too many open files”,這是由于打開檔案數已經達到了最大值,進而他們不能打開更多檔案,則可能需要增加該值。

4

5

6

7

8

9

10

11

12

13

<code>[root@localhost home]</code><code># vim /etc/rc.local </code>

<code>#!/bin/sh</code>

<code>#</code>

<code># This script will be executed *after* all the other init scripts.</code>

<code># You can put your own initialization stuff in here if you don't</code>

<code># want to do the full Sys V style init stuff.</code>

<code>echo</code> <code>222158 &gt; </code><code>/proc/sys/fs/file-max</code>    <code>;添加此項,修改</code><code>file</code><code>-max值</code>

<code>touch</code> <code>/var/lock/subsys/local</code>

<code>[root@localhost home]</code><code># reboot</code>

<code>[root@localhost ~]</code><code># cat /proc/sys/fs/file-max </code>

<code>222158</code>

<code>[root@localhost ~]</code><code>#</code>

修改此硬限制的方法是修改/etc/rc.local腳本,在腳本中添加如下行:

echo 22158 &gt; /proc/sys/fs/file-max

這是讓Linux在啟動完成後強行将系統級打開檔案數硬限制設定為22158。修改完後儲存此檔案。

/proc/sys/fs/file-nr 

該檔案與 file-max 相關,它有三個值: 

已配置設定檔案句柄的數目     已使用檔案句柄的數目     檔案句柄的最大數目 

該檔案是隻讀的,僅用于顯示資訊。

<code>[root@localhost ~]</code><code># cat /proc/sys/fs/file-nr </code>

<code>2112    0   222158</code>

修改系統檔案打開數:

通過修改/etc/security/limits.conf檔案,來修改目前系統檔案打開數,limits.conf的格式如下:  

&lt;domain&gt;      &lt;type&gt;  &lt;item&gt;         &lt;value&gt;

&lt;domain&gt; :可以指定單個使用者名、@組名、所有使用者(*)

<code>[root@localhost ~]</code><code># vim /etc/security/limits.conf   ;文末添加以下兩項</code>

<code>* hard nofile 65536       </code>

<code>* soft nofile 65536       ;或者直接使用* - nofile 65536</code>

<code>:wq</code>

我的是RedHat5.4修改後需要重新登陸,有的系統可能需要重新開機生效,

如果要修改max user processes 值,還需加上以下

* hard nproc 65535

* soft nproc 65535

nofile對應open_files

nproc對應max_user_processes

如果切換到其他非root使用者對應的max_user_processes沒改變,還需要修改以下檔案

/etc/security/limits.d/90-nproc.conf  (centos6)

/etc/security/limits.d/20-nproc.conf   (centos7)

<code>[root@localhost ~]</code><code># cat /etc/security/limits.d/20-nproc.conf </code>

<code># Default limit for number of user's processes to prevent</code>

<code># accidental fork bombs.</code>

<code># See rhbz #432903 for reasoning.</code>

<code>*          soft    nproc     65535</code>

<code>root       soft    nproc     unlimited</code>

要使 limits.conf 檔案配置生效,必須要確定 pam_limits.so 檔案被加入到啟動檔案中。檢視 /etc/pam.d/login 檔案中是否有以下選項,沒有直接文末添加:

<code>[root@localhost ~]</code><code># cat /etc/pam.d/login |grep "pam_limits.so"</code>

<code>session required </code><code>/lib/security/pam_limits</code><code>.so</code>

這是告訴Linux在使用者完成系統登入後,應該調用pam_limits.so子產品來設定系統對該使用者可使用的各種資源數量的最大限制(包括使用者可打開的最大檔案數限制),而pam_limits.so子產品就會從/etc/security/limits.conf檔案中讀取配置來設定這些限制值。

問題:修改完發現系統在本地無法登陸,遠端可以登陸,後來檢視了下日志如下

14

15

16

17

18

19

20

21

22

<code>[root@mail ~]</code><code># cat /var/log/secure</code>

<code>...</code>

<code>Nov 19 13:17:23 mail sshd[3000]: error: Bind to port 22 on 0.0.0.0 failed: Address already </code><code>in</code> <code>use.</code>

<code>Nov 19 13:17:38 mail runuser: pam_unix(runuser-l:session): session opened </code><code>for</code> <code>user amavis by (uid=0)</code>

<code>Nov 19 13:17:40 mail runuser: pam_unix(runuser-l:session): session closed </code><code>for</code> <code>user amavis</code>

<code>Nov 19 13:17:40 mail runuser: pam_unix(runuser-l:session): session opened </code><code>for</code> <code>user dspam by (uid=0)</code>

<code>Nov 19 13:17:41 mail runuser: pam_unix(runuser-l:session): session closed </code><code>for</code> <code>user dspam</code>

<code>Nov 19 13:17:54 mail login: PAM unable to dlopen(</code><code>/lib/security/pam_limits</code><code>.so)</code>

<code>Nov 19 13:17:54 mail login: PAM [error: </code><code>/lib/security/pam_limits</code><code>.so: wrong ELF class: ELFCLASS32]</code>

<code>Nov 19 13:17:54 mail login: PAM adding faulty module: </code><code>/lib/security/pam_limits</code><code>.so</code>

<code>Nov 19 13:17:57 mail login: pam_unix(login:session): session opened </code><code>for</code> <code>user root by LOGIN(uid=0)</code>

<code>Nov 19 13:17:57 mail login: Module is unknown</code>

<code>Nov 19 13:17:59 mail login: PAM unable to dlopen(</code><code>/lib/security/pam_limits</code><code>.so)</code>

<code>Nov 19 13:17:59 mail login: PAM [error: </code><code>/lib/security/pam_limits</code><code>.so: wrong ELF class: ELFCLASS32]</code>

<code>Nov 19 13:17:59 mail login: PAM adding faulty module: </code><code>/lib/security/pam_limits</code><code>.so</code>

<code>Nov 19 13:18:03 mail login: pam_unix(login:auth): authentication failure; </code><code>logname</code><code>=LOGIN uid=0 euid=0 </code><code>tty</code><code>=tty1 ruser= rhost=  user=csdp</code>

<code>Nov 19 13:18:05 mail login: FAILED LOGIN 1 FROM (null) FOR csdp, Authentication failure</code>

<code>Nov 19 13:18:22 mail sshd[3551]: Accepted password </code><code>for</code> <code>root from 10.15.44.69 port 57696 ssh2</code>

<code>Nov 19 13:18:22 mail sshd[3551]: pam_unix(sshd:session): session opened </code><code>for</code> <code>user root by (uid=0)</code>

<code>Nov 19 13:18:29 mail login: pam_unix(login:session): session opened </code><code>for</code> <code>user root by LOGIN(uid=0)</code>

<code>Nov 19 13:18:29 mail login: Module is unknown</code>

Nov 19 13:17:54 mail login: PAM [error: /lib/security/pam_limits.so: wrong ELF class: ELFCLASS32]

<code>[root@mail ~]</code><code># getconf LONG_BIT</code>

<code>64</code>

<code>[root@mail ~]</code><code>#</code>

系統是64位的,上面/etc/pam.d/login應該修改成64位檔案所在目錄,即

<code>session required </code><code>/lib64/security/pam_limits</code><code>.so</code>

修改後恢複正常

核心參數對檔案描述符也有限制,如果設定的值大于核心的限制,也是不行的,

查找file-max的核心參數:

<code>[root@alille-654-1-41-1 bin]</code><code># sysctl -a|grep file-max</code>

<code>fs.</code><code>file</code><code>-max = 753776</code>

<code>[root@alille-654-1-41-1 bin]</code><code>#</code>

更改file-max的核心參數:

<code>[root@alille-654-1-41-1 bin]</code><code># sysctl -w file-max=65535    ;臨時</code>

<code>[root@alille-654-1-41-1 bin]</code><code># vim /etc/sysctl.conf         ;永久</code>

<code>fs.</code><code>file</code><code>-max = 65535</code>

23

24

<code>2112    0   100977</code>

<code>[root@localhost ~]</code><code># ulimit -a    ;顯示目前資源限制的設定</code>

<code>core </code><code>file</code> <code>size          (blocks, -c) 0   </code>

<code>data seg size           (kbytes, -d) unlimited  </code>

<code>scheduling priority             (-e) 0</code>

<code>file</code> <code>size               (blocks, -f) unlimited  </code>

<code>pending signals                 (-i) 7922</code>

<code>max locked memory       (kbytes, -l) 64</code>

<code>max memory size         (kbytes, -m) unlimited</code>

<code>open</code> <code>files                      (-n) 1024                ;打開限制</code>

<code>pipe size            (512 bytes, -p) 8</code>

<code>POSIX message queues     (bytes, -q) 819200</code>

<code>real-</code><code>time</code> <code>priority              (-r) 0</code>

<code>stack size              (kbytes, -s) 10240</code>

<code>cpu </code><code>time</code>               <code>(seconds, -t) unlimited</code>

<code>max user processes              (-u) 7922</code>

<code>virtual memory          (kbytes, -</code><code>v</code><code>) unlimited</code>

<code>file</code> <code>locks                      (-x) unlimited</code>

<code>[root@localhost ~]</code><code># ulimit -n</code>

<code>1024</code>

如果需要臨時修改檔案數可以使用以下操作:

<code>[root@localhost ~]</code><code># ulimit -HSn 4096</code>

<code>4096</code>

H指定了硬性大小,S指定了軟性大小,n表示設定單個程序最大的打開檔案句柄數量,永久修改參考上面:修改系統檔案打開數

如何檢視目前系統打開檔案數最多的程式:

lsof -n 不将IP轉換為hostname,預設是不加上-n參數 eg:# lsof  /GTES11/

lsof -i 用以顯示符合條件的程序情況  eg:# lsof -i :22

<code>[root@localhost ~]</code><code># lsof -n|awk '{print $2}'|sort -nr|uniq -c|sort -nr|head -5</code>

<code>    </code><code>162 1812</code>

<code>    </code><code>149 1827</code>

<code>    </code><code>126 1591</code>

<code>    </code><code>107 1823</code>

<code>    </code><code>100 1826</code>

如何檢視某一程式打開檔案數:lsof -p pid

<code>[root@localhost ~]</code><code># lsof -p 1812|wc -l</code>

<code>163</code>

<code>[root@localhost ~]</code><code># lsof -p 1827|wc -l</code>

<code>150</code>

檢視某一程式最大打開檔案數:[root@alille-654-1-41-1 bin]# cat /proc/pid/limits 

<code>[root@alille-</code><code>654</code><code>-</code><code>1</code><code>-</code><code>41</code><code>-</code><code>1</code> <code>bin]# ps -ef|grep -i </code><code>"ProxyServer"</code>

<code>root     </code><code>12091</code> <code>12083</code> <code>99</code> <code>10</code><code>:</code><code>25</code> <code>pts/</code><code>0</code>    <code>05</code><code>:</code><code>32</code><code>:</code><code>45</code>  <code>proxyserver</code>

<code>[root@alille-</code><code>654</code><code>-</code><code>1</code><code>-</code><code>41</code><code>-</code><code>1</code> <code>bin]# cat /proc/</code><code>12091</code><code>/limits </code>

<code>Max open files            </code><code>65535</code>                <code>65535</code>                <code>files</code>

 ulimit 指令詳解

ulimit用于shell啟動程序所占用的資源,是shell内建指令。

參數介紹:

-H 設定硬體資源限制.

-S 設定軟體資源限制.

-a 顯示目前所有的資源限制.

-c size:設定core檔案的最大值.機關:blocks

-d size:設定資料段的最大值.機關:kbytes

-f size:設定建立檔案的最大值.機關:blocks

-l size:設定在記憶體中鎖定程序的最大值.機關:kbytes

-m size:設定可以使用的常駐記憶體的最大值.機關:kbytes

-n size:設定核心可以同時打開的檔案描述符的最大值.機關:n

-p size:設定管道緩沖區的最大值.機關:kbytes

-s size:設定堆棧的最大值.機關:kbytes

-t size:設定CPU使用時間的最大上限.機關:seconds

-v size:設定虛拟記憶體的最大值.機關:kbytesLinux

啟用記錄Core dump檔案功能

在linux下,設定core檔案打開之後,當程序異常退出時,作業系統會在程序工作目錄下,生成一個core 檔案,檔案名一般是:core.程序号。

一、啟用記錄Core檔案功能

通過linux的ulimit指令用 –c參數設定core檔案的大小,如:ulimit  –c unlimited 則表示不限制core檔案的大小,設定具體的數值表示core檔案的位元組數。

a、檢視目前是否已經打開了此開關

<code>[root@localhost ~]</code><code># ulimit -c</code>

<code>0</code>

ulimit -c 如果輸出為 0 ,則代表沒有打開。如果為unlimited則已經打開了

 b、開啟

臨時開啟:

<code>[root@localhost ~]</code><code># ulimit -c unlimited</code>

<code>unlimited</code>

<code>[root@localhost ~]</code><code># ulimit -c 0</code>

通過ulimit -c unlimited指令打開此功能,切不限制core檔案的大小,如果要取消,執行指令ulimit -c 0 就可以了

永久開啟:

在/etc/profile檔案中一般可以找到:ulimit -S -c 0 &gt; /dev/null 2&gt;&amp;1,根據上面的例子,我們隻要把那個0 改為 unlimited 就ok了,如果沒有直接在文末添加,然後儲存退出。通過source /etc/profile 使當期設定生效,重新開機系統

<code>[root@localhost ~]</code><code># vim /etc/profile</code>

<code>ulimit</code> <code>-S -c unlimited</code>

<code>[root@localhost ~]</code><code># source /etc/profile</code>

二、檢視Core檔案日志方法

通常使用gdb工具察看這個core 檔案,gdb是linux自帶的一個調試工具,比較容易定位到發生異常的函數名。比如運作一個程序,發生異常退出,則在工作目錄下生成一個core.xxxxx的檔案,可以運作gdb檢視:

gdb 程序名 core.xxxxxx 回車,輸入 where 指令,即會列出異常時的函數調用棧。一般為了保證環境一緻性,需要在本機上執行gdb察看core檔案。

eg:gdb httpd -c core.1309

      Where

core dump檔案名的模式儲存在/proc/sys/kernel/core_pattern中,預設值是core。通過以下指令可以更改core dump檔案的位置(如希望生成到/tmp/cores目錄下)echo “/tmp/cores/core” &gt; /proc/sys/kernel/core_pattern

本文轉自 justin_peng 51CTO部落格,原文連結:http://blog.51cto.com/ityunwei2017/1558092,如需轉載請自行聯系原作者

繼續閱讀