ulimitについて
ulimitとは?
man ulimt
を実行すると、bashのmanが。。。その中のulimit部分には以下の記載があり。
Provides control over the resources available to the shell and to processes started by it, on systems that allow such control.
→シェルもしくは、シェルから起動したプロセスに対して、利用可能なリソースを制限をする。
制御できるリソース
ulimit -a
で確認できる。色々ある。
ulimit -a | egrep -v unlimited
この中で、よく問題になるのは、-nのオープン可能なファイル数。
ファイルディスクリプタ使用状況の確認方法
ls /proc/[PID]/fd/
※このディレクトリ配下のエントリ数=利用しているファイルディスクリタ数となる。
制限値としてソフトとハードの2つあり。
ソフトが適用される制限値。
ハードはユーザーが変更可能な上限値。
使い分け、制御の動きとしては、こんな感じ。
例)ファイルディスクリプタの場合。
# ulimit -Sn
1024
※-Sはソフトリミット指定
※-nはファイルディスクリプタ指定
# (find / -type f | head -1020 | xargs tail -f) > /dev/null
これはエラー出ない。この場合、ファイルオープンしているプロセスはtailになる。
tailコマンドがどれくらいファイルをオープンしているかというと、、、
# ps -C tail -o pid= | xargs -i find /proc/{}/fd ! -type d | wc -l
1024
ぎりぎりだ。ってことは、
# (find / -type f | head -1021 | xargs tail -f) > /dev/null
tail: inotify cannot be used, reverting to polling: Too many open files
エラーが出る!!
ちなみに、開けるところまでは開いているみたい。
# ps -C tail -o pid= | xargs -i find /proc/{}/fd ! -type d | wc -l
1024
ってことで、リミットを一つ上げてみる
# ulimit -Sn 1025
# (find / -type f | head -1021 | xargs tail -f) > /dev/null
エラーはでなくなる。
こんな感じでソフトリミットは制限ではあるが、変更可能。変更可能な範囲がハードリミットで定義されている。
# ulimit -Hn
4096
なので、以下コマンドはエラーになる。
# ulimit -Sn 4097
- bash: ulimit: open files: cannot modify limit: Invalid argument
rootユーザーであれば、このハードリミットすら変更可能。
# ulimit -Hn 10000
# ulimit -Hn
10000
もちろん、一般ユーザーでは変更できるのはソフトリミットのみ。
デーモンはどう制御されているの?
起動スクリプトから起動されるデーモンの場合、起動スクリプトの中でulimitコマンドで制御可能。ただ、以下の挙動があった。
・postfixの起動スクリプト内でulimit -Sn 1024記載
・postfixのプロセスのオープン可能なファイル数を調べたところ、
# egrep "Max open files" /proc/[PID]/limits
・ソフトもハードも4096になってる。。。。。これはどうやらデーモンが起動する時に起動シェルのハードリミットまでソフトリミットを上げていると思われる。
・ためしに、起動スクリプト内でulimit -Hn 1024を実行するとプロセスのソフトもハードも1024になっていた。
他ファイルディスクリプタ関連で便利なコマンド
システム全体で利用可能な最大ファイルディスクリプタ数は
sysctl fs.file-max
※この数値は、物理メモリサイズで決まるみたい。
システム全体で利用中のファイルディスクリプタ数は
sysctl fs.file-nr
この出力の1列目の数値。ただ、この値はメモリが割り当てられたファイルディスクリプタの数。よって、単純にtcp接続し、ソケットを利用したとしても、データのやりとりをしないと、メモリが割り当てられない為、このカウンタには反映しない。
例)
(tail -f /tmp/b | telnet 192.168.46.128 80) &
※/tmp/bは空のファイル。これではtcp接続しただけなので、ESTABLISHEDにはなったがサーバ側のsysctl fs.file-nrの値は変わらなかった。
ulimitであと気になる事として、、、、
$ ulimit -aS | egrep "max user processes"
max user processes (-u) 1024
$ ulimit -aH | egrep "max user processes"
max user processes (-u) 1024
$
これは要注意!!!プロセスに対する制限ではなくユーザーに対する制限!!!
動作を確認すると、
$ ps -u pike |wc -l;NUM=0;while [ $NUM -le 1000 ]; do (sleep 100 &) ; NUM=`expr $N
UM + 1`; done;ps -u pike | wc -l
5
1006
$
これは大丈夫だけど、以下だと。。。。
$ ps -u pike |wc -l;NUM=0;while [ $NUM -le 1024 ]; do (sleep 100 &) ; NUM=`expr $N
UM + 1`; done;ps -u pike | wc -l
5
- bash: fork: retry: Resource temporarily unavailable
- bash: fork: retry: Resource temporarily unavailable
- bash: fork: retry: Resource temporarily unavailable
- bash: fork: retry: Resource temporarily unavailable
- bash: fork: Resource temporarily unavailable
こんな感じでエラーが出る。
これは、Cent6では要注意だ!!!
ちなみに、rootユーザーでは、/etc/security/limits.d/90-nproc.confでは無制限と書いてあるけど、ulimit -uではメモリが512MBの環境では3699って出た。ためしにメモリ1Gbの場合だと、7747って出た!!!
ちなみに、この値で制限は動くかというと、、、、
※ulimit -uの結果が3699のホストで以下を実行
# ps -u root |wc -l;NUM=0;while [ $NUM -le 3699 ]; do (sleep 1000 &) ; NUM=`expr $NUM + 1`; done;ps -u pike | wc -l
→3699以上起動するじゃん!!!
これは、物理メモリに対する起動プロセス数の目安なのかな。。。。どこで動くかは分かりません。。。
あとこれも要注意!!
rootユーザーから任意のユーザーにスイッチして起動するプロセスは制限を受けるのか?
# while [ $NUM -le 1050 ]; do (sudo -u pike sleep 1000 &); NUM=`expr $NUM + 1`; done
※一般ユーザーは1024だけど、上記コマンドはエラーとはならない。
- 最終更新:2014-12-14 17:55:25