致前輩:該問題的解決思路給了我很大的啟發,文章作者Lis, Linux資深技術專家。
問題現象:這是一個基於Java的web應用系統,在后台添加數據時提示無法添加,於是登陸服務器查看Tomcat 日志,發現如下異常信息,java.io.IOException:too many open files
通過這個報錯信息,基本判斷是系統可以使用的文件描述符不夠了,由於Tomcat服務系統www用戶啟動的,於是以www 用戶登陸系統,通過ulimit -n 命令查看系統可以打開最大文件描述符的數量:
$ ulimit -n
65535
可以看到這台服務器設置的最大可以打開的文件描述符已經是65535了,這么大的值應該夠用了,但是為什么提示這樣的錯誤呢?
解決思路,這個案例涉及ulimit 命令的使用
在使用ulimit 時,有以下幾種使用方法:
1.在用戶環境變量中加入
如果用戶使用的是bash,那么可以在用戶目錄的環境變量文件.bashrc或者.bash_profile中加入 ulimit -u 128 來限制用戶最多可以使用128個進程
2.在應用程序的啟動腳本中加入
如果應用程序是Tomcat, 那么可以再Tomcat 的啟動腳本startup.sh 中加入 ulimit -n 65535 來閑置用戶最多可以使用65535個文件描述符
3.直接在shell命令終端執行ulimit 命令
這種方法的資源限制僅僅在執行命令的終端生效,在退出或者和關閉終端后,設置失效,並且這個設置不影響其他shell 終端
解決問題:
在了解ulimit 知識后,接着上面的案例,既然ulimit 設置沒有問題,那么一定是設置沒有生效導致的,接下來檢查下啟動 Tomcat 的 www 用戶環境變量是否添加 ulimit 限制,檢查后發現,www 用戶並無ulimit限制。於是繼續檢查Tomcat 啟動腳本startup.sh 文件是否添加了 ulimit限制,檢查后發現也沒有添加。最后考慮是否將限制加到了limits.conf文件中,於是檢查limits.conf 文件,操作如下
#cat /etc/security/limits.conf | grep www
www soft nofile 65535
www hard nofile 65535
從輸出可知,ulimit限制加在limits.conf文件中,既然限制已經添加了,配置 也沒有什么錯,為何還會報錯,經過思考,判斷只有一種可能,那就是Tomcat 的啟動時間早於ulimit 資源限制的添加時間,於是首先查看下Tomcat 啟動時間,操作如下
#uptime
Up 283 days
#pgrep -f tomcat
4667
#ps -eo pid, lstart, etime | grep 4667
4667 Sat Jul 6 09;33:39 2013 77-05:26:02
從輸出可以看出,這台服務器已經有283天沒有重啟了,而Tomcat 是在2013年7月6號9點啟動的,啟動了將近77天,接着看看limits.conf文件的修改時間,
#stat /etc/security/limits.conf
通過stat 命令清楚的看到,limits.conf文件最后的修改時間是2013年7月12日,晚於Tomcat啟動時間,如此,重啟Tomcat之后問題解決。
感悟:排查問題的思路清晰,循序漸進,最出彩的是排錯過程中對各種細節的把握,服務的啟動時間與配置文件的修改時間,這個細節讓我很是受益,不虧是老運維出來的扎實功底。再敬 前輩。