programer squidを使っていたら次のようなエラーが発生していて、
やたら重かったので調べていたらファイルディスクリプタという聞きなれない言葉をハヶ━m9( ゚д゚)っ━ン!!

squidのエラー内容

2013/04/16 14:37:58| WARNING! Your cache is running out of filedescriptors


squildの実際に使われている値の確認
※squidが起動している状態で実行する。-hにはsquidサーバーを指定する




squidclient -h 192.168.0.20 -p 80 mgr:info| grep 'file descri'
#ファイルディスクリプタの最大値
Maximum number of file descriptors:   1024
#ファイルディスクリプタの空きすう
Available number of file descriptors: 1005
#ファイルディスクリプタの予約数
Reserved number of file descriptors:   100



こちらのサイトで分かりやすく書かれていました! ファイルディスクリプタ数の上限変更とlimits.confの罠 一部抜粋です( ´∀`)bグッ!

Linuxでは、同時にオープンできるファイルディスクリプタ数が制限されています。
OS全体での設定は、/proc/sys/fs/file-max等で確認でき、大規模なアクセスがあるサーバでは/etc/sysctl.confに設定を追加して上限を増やしているケースも多いでしょう。

これとは別に、1プロセスが同時オープン可能なファイルディスクリプタ数は、標準で1024となっています。
apacheのpreforkモデル等の子プロセスが多数稼動するアプリケーションだと、
1プロセスあたりのファイルオープン数はそこまで増加しないので、普段はあまり意識することは少ないかもしれません。
しかし、apacheのworkerモデル等のスレッドを使用するアプリケーションでは、この制限が致命的になるケースが発生します。

とのことです。(´・∀・`)ヘー

そんで、squidは1プロセスしか立ち上がらないので、上記のサイトの説明に書かれている
apacheのworkerモデルに該当するっぽいです。

そのため、同時オープン可能なファイルディスクリプタ数はデフォルト設定の1024になっていると思われます。

まずは、OS全体のでのファイルディスクリプタ数の設定の確認を行ってみます(゚д゚)(。_。)(゚д゚)(。_。) ウンウン
次のコマンドを実行すると、左から、割り当て済みファイルディスクリプタ(17824) 、
使用中ファイルディスクリプタ(0) 、最大割り当て可能ファイルディスクリプタ(785338)となる。



cat /proc/sys/fs/file-nr
17824   0       785338


OS全体では最大値が785338がなっているようでした。

OS全体でのファイルディスクリプ値



sudo cat /proc/sys/fs/file-max
785338



現在のファイルディスクリプタの使用状況
左から、割り当て済みファイルディスクリプタ 、使用中ファイルディスクリプタ 、最大割り当て可能ファイルディスクリプタとなる。



sudo cat /proc/sys/fs/file-nr
17824   0       785338





この最大割り当て可能ファイルディスクリプタの値を増やしてみる。/etc/sysctl.conf を開いて、最下行に以下のように追記する。



sudo vi /etc/sysctl.conf
 
# ファイルディスクリプタの上限値
fs.file-max = 794573


ここでは最大割り当て可能値を794573とした。この設定を反映させる為に以下のコマンドを実行する。


$ sudo sysctl -p
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
error: "net.bridge.bridge-nf-call-ip6tables" is an unknown key
error: "net.bridge.bridge-nf-call-iptables" is an unknown key
error: "net.bridge.bridge-nf-call-arptables" is an unknown key
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
fs.file-max = 794573


sudo cat /proc/sys/fs/file-nr
17824   0       785338



各ユーザのファイルディスクリプタの上限値を変更する

現在ログイン中のユーザーのファイルディスクリプタの上限値の確認



ulimit -n
1024


指定ユーザーのファイルディスクリプタの変更
/etc/security/limits.d/に拡張子をconfにしたファイルをおけば、
自動で読み込んでくれるっぽい。




ls -alt /etc/security/limits.d/
合計 12
drwxr-xr-x. 6 root root 4096  2月 25 09:56 2013 ..
drwxr-xr-x. 2 root root 4096  2月 25 09:56 2013 .
-rw-r--r--. 1 root root  152  4月 16 18:04 2012 90-nproc.conf

squid用の設定ファイルを作成する。



vi /etc/security/limits.d/squid.conf
######################
#
# squidの設定
#
######################
 
#OSの最大値785338
* soft nofile 10000
* hard nofile 10000





ただし、注意として、limits.dの設定ファイルで変更できるのは、
一時的なもので、OSの再起動や

また「ファイルディスクリプタ数の上限変更とlimits.confの罠」次から抜粋ですが、 つまり、「PAM認証を介さないようなdaemon系プログラムの制限には/etc/security/limits.confは使えない」ことになるのです。

daemon系プロセスのファイルディスクリプタ数上限を設定する際、/etc/security/limits.conf は使えません。
状況によっては一見設定されたように見えますが、大きな落とし穴にはまることになります。
面倒ですが、必要なプロセス毎にulimitを用いて適切に設定しましょう。

確認のためにsquidユーザーになろうとするが、
ログインが出来ないユーザーで作成してあった・・・orz




sudo su - squid
This account is currently not available.


nologin:(;゙゚’ω゚’): #設定の確認



cat /etc/passwd|grep squid
squid:x:23:23::/var/spool/squid:/sbin/nologin



そこで、ログインできるようにする。



usermod -s /bin/bash squid



設定の確認




cat /etc/passwd|grep squid
squid:x:23:23::/var/spool/squid:/bin/bash


ログイン成功




# sudo su - squid
-bash-4.1$


squidユーザーになったら、先程設定したファイルディスクリプタの上限値を確認する



$ ulimit -n
10000




squidユーザーのファイルディスクリプタの上限値をあげたので、
反映されるために、squidを一度停止してから起動を行います。
suqid -k reconfigureでは反映されません。

再起動後に、次のコマンドで反映されていることを確認する。



squidclient -h squidサーバーのIPアドレス -p 80 mgr:info| grep 'file descri'
        Maximum number of file descriptors:   10000
        Available number of file descriptors: 9055
        Reserved number of file descriptors:   100





以上です(`・ω・´)ゞビシッ!!
参考URL

この記事を書いた人

nakajima
nakajima
企画開発部のエンジニアです。プログラム、サーバーもどっちも楽しくて好きですが最近はサーバーの方がメインになってる気がします。