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

このWIKIを編集するにはパスワード入力が必要です

認証パスワード