昨晚收到服務器報警郵件,提示如下:
open /dev/null: too many open files
顯然是服務器中打開的文件數太多,準確地說是某個進程打開的文件數太多。那麼,我們先看下進程能夠佔用的最大文件描述符數是多少。
[root@i data0]# 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) 95000
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) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 95000
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
由輸出結果中的指標open files可知,當前系統一個進程能夠打開的最大文件數是1024。顯然可以增大這個值,有兩種方法,一是直接執行命令:
ulimit -n 16384
但這種方式起的作用是臨時的,如果想永久的生效,則需要修改配置文件limits.conf文件,在其末尾加上如下兩行:
* soft nofile 16384
* hard nofile 16384
然後註銷重啓就可以了。這裏順帶說下limits.conf文件的原理。limits.conf是pam_limits.so的配置文件,/etc/pam.d/下的應用程序調用pam_***.so模塊。當用戶訪問服務器,服務程序將請求發送到PAM模塊,PAM模塊根據服務名稱在/etc/pam.d 目錄下選擇一個對應的服務文件,然後根據服務文件的內容選擇具體的PAM模塊進行處理。
例:限制admin用戶登錄到sshd的服務不能超過2個 在/etc/pam.d/sshd 中添加 session required pam_limits.so;在/etc/security/limits.conf中添加 admin - maxlogins 2
其實還可以看看是哪個進程佔用的文件描述符數超了,這裏就要用到lsof命令了。
[root@localhost data0]# lsof | more
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
init 1 root cwd DIR 8,3 4096 2 /
init 1 root rtd DIR 8,3 4096 2 /
init 1 root txt REG 8,3 150352 81983 /sbin/init
init 1 root mem REG 8,3 65928 114718 /lib64/libnss_files-2.12.so
init 1 root mem REG 8,3 1922152 115146 /lib64/libc-2.12.so
init 1 root mem REG 8,3 93224 115162 /lib64/libgcc_s-4.4.7-20120601.so.1
init 1 root mem REG 8,3 47064 115149 /lib64/librt-2.12.so
init 1 root mem REG 8,3 145720 115148 /lib64/libpthread-2.12.so
init 1 root mem REG 8,3 268232 115150 /lib64/libdbus-1.so.3.4.0
init 1 root mem REG 8,3 39896 114918 /lib64/libnih-dbus.so.1.0.0
init 1 root mem REG 8,3 101920 114920 /lib64/libnih.so.1.0.0
init 1 root mem REG 8,3 156872 115145 /lib64/ld-2.12.so
init 1 root 0u CHR 1,3 0t0 3842 /dev/null
init 1 root 1u CHR 1,3 0t0 3842 /dev/null
init 1 root 2u CHR 1,3 0t0 3842 /dev/null
init 1 root 3r FIFO 0,8 0t0 7312 pipe
這裏列出的就是所有打開的文件數,第二列是每個打開的文件對應的進程id。另外這裏顯示的也只是一小部分,實際上還有很多。這時可以執行以下命令查看每個進程對應的打開的文件數。
[root@localhost data0]# lsof | awk '{print $2}' | uniq -c | sort -rn | head -n 10
89 24833
77 23132
73 31469
70 9557
69 26242
68 8893
68 8643
68 8626
68 26210
68 13002
結果中顯示的第二列是進程id,第一列是該進程打開的文件數,可見pid爲24833的進程打開的文件數最多,並按從多到少排列。知道pid後,就可以通過ps -ef | grep pid查看對應的進程,之後要殺要剮悉聽尊便。