Linuxでは、各プロセスが利用できるさまざまなリソースに一定の制限がかけられています。大量のリソースを消費するアプリケーションを実行する場合や多数のユーザーがアクセスする環境では、このようなリソースの制限にも注意を払う必要があります。

詳細は後述しますが、リソースの制限値には、ソフトリミットとハードリミットの2種類の値があります。ソフトリミットは現在有効な制限値です。以下は、ソフトリミットの確認例です。

# ulimit -Sa
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 3829
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) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 3829
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

特に注意が必要な設定は次のとおりです。

core file size」は、QUITコマンドシグナルを受信して終了した際に作成する、コアダンプのファイルサイズを制限します。単位は「KB」です。0の場合は、コアダンプは作成されません。

file size」は、プロセスが作成可能なファイルのサイズを制限します。この制限を超過すると「File size limit exceeded」のエラーが発生します。unlimitedの場合は制限しません。

open files」は、プロセスが同時にオープン可能なファイル数を制限します。後述するファイルディスクリプタ数の上限のことです。

max user processes」は、このユーザーが起動可能なプロセスの数を制限します。プロセスに対する制限ではなく、ユーザーに対する制限になります。

これらの設定値は、ulimitコマンドで変更します。

利用可能なソケット数の上限

インターネットに公開したWebサーバーなど、多数のネットワーク接続が発生するシステムでは、サーバー上で、同時に利用できるソケット数が上限に達して、それ以上クライアントの接続が受け付けられなくなることがあります。
この上限値を決めるパラメータには、プロセスごとに設定される「ファイルディスクリプタ数」の上限と、サーバー全体で設定される「ファイルオブジェクト数」の上限があります。

ファイルディスクリプタ数の上限

Linuxでは、個々のプロセスが同時にオープンできるファイル数をulimitによって制限する機能を持ちます。
これは、正確には個々のプロセスが使用できるファイルディスクリプタ数の上限になります。
ファイルディスクリプタは、Linuxカーネルが管理する各プロセスがオープン中のファイルを識別するラベルです。

Linuxはいろいろなものをファイルとして表現しようとする特徴があります。
Linuxでは、仮想ファイルシステムの機能により、物理ディスク上のファイル以外にも、標準入出力やTCPソケットなどのリソースも仮想的にファイルとして扱います。つまり、それらのリソースを使用する際もファイルディスクリプタが必要となります。
従って、HTTPデーモンなど、ネットワーク通信を多用するプロセスでは、ulimitによるファイルディスクリプタ数の制限により、同時接続可能なクライアント数が制限される場合があります。
多数のネットワーク接続が予想されるシステムでは、ulimitによるファイルディスクリプタ数の制限を増やしておく必要があります。
ファイルディスクリプタ数の上限を変更する方法は複数あるので、目的に応じて選択します。
使用するアプリケーションやミドルウェアで変更方法が指定されている場合もあります。そのため、各アプリケーションやミドルウェアのマニュアルも確認する必要があります。

ログインシェルに対して設定する

まず、ユーザーのログインシェルに対して設定する場合は、設定ファイル「/etc/security/limits.conf」に記述します。
soft(ソフトリミット)が実際の制限値で、hard(ハードリミット)は、個々のユーザーがulimitコマンドで変更する際の変更可能な上限値です。これらは実際に設定したい値に変更する。

起動中のシェルの実際の設定値は、次のコマンドで確認できます。それぞれソフトリミットとハードリミットを表示します。

# ulimit -Sn
1024
# ulimit -Hn
4096

このシェルから起動したプロセスはこの設定値を引き継ぎます。
また、各ユーザーはログインシェルからulimitコマンドで設定値を変更できます。
次のコマンドはソフトリミットを変更する例です。

# ulimit -Sn 4096

ただし、ハードリミットを越える値は指定できません。
次のコマンドはハードリミットを変更する例です。rootユーザー以外は、ハードリミットの値を増加させることはできません。減少させることだけ可能です。

# ulimit -Hn 8192

次のコマンドは、ソフトリミットとハードリミットを同時に変更する例です。

# ulimit -n 8192

サーバー起動時に自動起動されるプロセスに対して設定する

ユーザーのログインシェル以外に、サーバー起動時に自動起動されるプロセスに対して設定する場合は、ファイル「/etc/initscript」を作成します。
「/etc/initscript」が事前に存在する場合は、ulimitの行を最後のexecの前に追加します。これにより、initから起動されるすべてのプロセスに対して、ここに記載したulimitが適用されます。

# vi /etc/initscript
ulimit -Hn 60000
ulimit -Sn 2048
eval exec "$4"

専用の起動シェルスクリプトを持つプログラムに設定する場合

最後に専用の起動シェルスクリプトを持つプログラムに設定する場合は、先に説明したulimitコマンドを起動シェルスクリプトに追加します。
起動シェルスクリプトが、root以外のユーザーで起動される場合は、ハードリミットの増加はできませんので、ハードリミットの増加が必要な場合は、「/etc/initscript」を利用するか、起動シェルスクリプト自身を起動するrootユーザーが権限のスクリプトを用意して、そこでハードリミットを増加するなどの方法をとります。

使用中のファイルディスクリプタを確認する方法

各プロセスが使用中のファイルディスクリプタを確認するには、プロセスIDをとして、次のコマンドを実行します。

# ls -l /proc//fd

例えば、PostgreSQLのファイルオープン数を確認するには以下のコマンドを実行します。

# ps -ef | grep postgres | grep -v grep
postgres   1808      1  0 08:08 ?        00:00:00 /usr/pgsql-9.5/bin/postgres -D /var/lib/pgsql/9.5/data
# ls -l /proc/1808/fd
合計 0
lr-x------. 1 postgres postgres 64  1月  2 08:13 0 -> /dev/null
l-wx------. 1 postgres postgres 64  1月  2 08:13 1 -> pipe:[19487]
lrwx------. 1 postgres postgres 64  1月  2 08:13 10 -> socket:[19525]
l-wx------. 1 postgres postgres 64  1月  2 08:13 2 -> pipe:[19487]
lrwx------. 1 postgres postgres 64  1月  2 08:13 3 -> socket:[19296]
lrwx------. 1 postgres postgres 64  1月  2 08:13 4 -> socket:[19297]
lrwx------. 1 postgres postgres 64  1月  2 08:13 5 -> socket:[19299]
lrwx------. 1 postgres postgres 64  1月  2 08:13 6 -> socket:[19302]
lr-x------. 1 postgres postgres 64  1月  2 08:13 7 -> pipe:[19360]
l-wx------. 1 postgres postgres 64  1月  2 08:13 8 -> pipe:[19360]
lr-x------. 1 postgres postgres 64  1月  2 08:13 9 -> pipe:[19487]

各プロセスが使用中のファイルディスクリプタと、それに対応するファイルの一覧が表示されます。