Linuxのulimitコマンド完全ガイド

Linuxシステムは各ユーザーに対してプロセス数の最大値を制限しています。システムのパフォーマンスを最適化するため、デバイスのリソース状況に応じて各Linuxユーザーの最大プロセス数を設定することが可能です。

現在の各種ユーザープロセス制限を表示するには、ulimit -aコマンドを使用します。以下に、あるLinuxユーザーの最大プロセス数を10000に設定する例を示します:

ulimit -u 10240

多くのソケット接続を保持する必要があるJavaアプリケーションの場合、各プロセスが開くことができるファイル数をulimit -n xxで増やすことが推奨されます。デフォルト値は1024です。ulimit -n 4096と設定することで、各プロセスが開くことができるファイル数を4096に増やすことができます(デフォルトは1024)。

その他、無制限(unlimited)に設定することが推奨される重要な設定は以下の通りです:

  • データセグメントの長さ:ulimit -d unlimited
  • 最大メモリサイズ:ulimit -m unlimited
  • スタックサイズ:ulimit -s unlimited
  • CPU時間:ulimit -t unlimited
  • 仮想メモリ:ulimit -v unlimited

一時的な設定では、ulimitコマンドを使用してログインしたシェルセッション期間中に適用されます。 永続的な設定では、ログインシェルが読み取るファイルに対応するulimit文を追加することで実現できます。つまり、シェル固有のユーザーリソースファイル(以下に例を示します)です:

1)、Linuxシステムの最大プロセス数と最大ファイルオープン数の制限を解除:

vi /etc/security/limits.conf
# 以下の行を追加
* soft noproc 11000
* hard noproc 11000
* soft nofile 4100
* hard nofile 4100

説明:*はすべてのユーザーを対象とし、noprocは最大プロセス数、nofileは最大ファイルオープン数を表します。

2)、SSHがLoginプログラムのログインを受け入れるようにし、SSHクライアントからulimit -aでリソース制限を確認できるようにする:

vi /etc/ssh/sshd_config
# UserLoginの値をyesに変更し、#のコメントを削除
# sshdサービスを再起動:
/etc/init.d/sshd restart

3)、すべてのLinuxユーザーの環境変数ファイルを変更:

vi /etc/profile
ulimit -u 10000
ulimit -n 4096
ulimit -d unlimited
ulimit -m unlimited
ulimit -s unlimited
ulimit -t unlimited
ulimit -v unlimited

保存後、#source /etc/profileを実行して設定を有効にします。

プログラム内で複数のファイルを開いて分析する必要がある場合、システムのデフォルト設定は通常1024です(ulimit -aで確認可能)。通常の使用には十分ですが、プログラムの場合は少なすぎます。2つのファイルを変更します。

1./etc/security/limits.conf

vi /etc/security/limits.conf
# 以下を追加:
* soft nofile 8192
* hard nofile 20480

2./etc/pam.d/login

/etc/pam.d/login
session required /lib/security/pam_limits.so

/**********
また、/etc/pam.d/system-authファイルに以下の内容があることを確認してください
session required /lib/security/$ISA/pam_limits.so
この行はシステムがこの制限を実行することを保証します。

/***********
3.一般ユーザーの.bash_profile

ulimit -n 1024

再ログインして完了

ulimitの役割
ulimit:ユーザーが使用できるリソースの制限(limit)を表示(または設定)します。この制限はソフト制限(現在の制限)とハード制限(上限)に分かれており、ハード制限はソフト制限の上限値です。アプリケーションは実行過程で対応するソフト制限を超えるシステムリソースを使用してはならず、いかなる超過もプロセスの終了を引き起こします。

パラメータ 説明 ulimited ユーザーが使用できるリソースを制限しませんが、この設定は最大ファイルオープン数(max open files)と同時実行可能な最大プロセス数(max user processes)には適用されません

  • -a すべての現在のリソース制限を一覧表示
  • -c coreファイルの最大値を設定。単位:blocks
  • -d プロセスのデータセグメントの最大値を設定。単位:kbytes
  • -f シェルが作成するファイルの最大サイズを設定。単位:blocks
  • -h 特定のリソースのハード制限を指定します。ユーザーがroot権限を持っている場合、ハード制限を増やすことができます。いかなるユーザーもハード制限を減らすことができます
  • -l ロック可能な物理メモリの最大値
  • -m 使用可能な常駐メモリの最大値。単位:kbytes
  • -n 各プロセスが同時に開くことができる最大ファイル数
  • -p パイプの最大値を設定。単位はblockで、1block=512bytes
  • -s スタックの最大値を指定:単位:kbytes
  • -S 特定のリソースのソフト制限を設定します。ソフト制限はハード制限の値まで増やすことができます。-Hと-Sフラグの両方が指定されていない場合、制限は両方に適用されます
  • -t 各プロセスが使用する秒数を指定。単位:seconds
  • -u 同時実行可能な最大プロセス数
  • -v シェルが使用できる最大仮想メモリ。単位:kbytes
  • -x

例1:

[root@localhost proc]# ulimit -a
core file size (blocks, -c) 100
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
pending signals (-i) 2047
max locked memory (kbytes, -l) 32
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 2047
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
[root@localhost proc]#

出力の各行はリソース名、(単位、ulimitコマンドのパラメータ)、ソフト制限で構成されます。詳細な説明: パラメータ 説明

  • core file size coreファイルの最大値は100ブロック
  • data seg size プロセスのデータセグメントは任意の大きさにできます
  • file size ファイルは任意の大きさにできます
  • pending signals 最大2047個の保留中のシグナルがあります
  • max locked memory 1つのタスクがロックできる物理メモリの最大値は32KB
  • max memory size 1つのタスクの常駐物理メモリの最大値
  • open files 1つのタスクは最大1024個のファイルを同時に開くことができます
  • pipe size パイプの最大スペースは4096バイト
  • POSIX message queues POSIXメッセージキューの最大値は819200バイト
  • stack size プロセスのスタックの最大値は8192バイト
  • cpu time プロセスが使用するCPU時間
  • max user processes 現在のユーザーが同時に開くことができるプロセス(スレッドを含む)の最大数は2047
  • virtual memory プロセスの最大アドレス空間に制限はありません
  • file locks ロックできるファイルの最大数に制限はありません

例2:ulimitコマンドを使用してファイルサイズを制限し、コピーコマンドが失敗するようにする

[root@localhost]ls temp.txt
ls: temp.txt: そのようなファイルやディレクトリはありません
[root@localhost]ulimit -f 1 #作成するファイルの最大ブロックを設定(1ブロック=512バイト)
[root@localhost]cat a.c > temp.txt

ファイルサイズが制限を超えています ファイルa.cのサイズは5002バイトですが、設定した作成ファイルのサイズは512バイト×1ブロック=512バイトです

1、ユーザープロセスのファイルオープン数制限を変更する

Linuxプラットフォーム上で、クライアントプログラムでもサーバープログラムでも、高並発TCP接続処理を行う場合、最高の並発数はシステムがユーザーの単一プロセスで同時に開くことができるファイル数の制限によって制限されます(これはシステムが各TCP接続ごとにソケットハンドルを作成し、各ソケットハンドルもファイルハンドルであるためです)。ulimitコマンドを使用して、システムが現在のユーザープロセスで開くことを許可しているファイル数の制限を確認できます:

[speng@as4 ~]$ ulimit -n
1024

これは現在のユーザーの各プロセスが最大1024個のファイルを同時に開くことを許可していることを示しています。この1024個のファイルから、各プロセスが必ず開いている標準入力、標準出力、標準エラー、サーバーリスニングソケット、プロセス間通信のUnixドメインソケットなどのファイルを差し引くと、クライアントソケット接続に使用できるファイル数は約1024-10=1014個程度しか残りません。つまり、デフォルトでは、Linuxベースの通信プログラムは最大1014個のTCP同時接続を許可するだけです。

より多くのTCP同時接続をサポートする必要がある通信処理プログラムの場合、Linuxの現在のユーザーのプロセスが同時に開くファイル数のソフト制限(soft limit)とハード制限(hardlimit)を変更する必要があります。ソフト制限はLinuxが現在のシステムが許容できる範囲内でユーザーが同時に開くファイル数をさらに制限するものであり、ハード制限はシステムのハードウェアリソース状況(主にシステムメモリ)から計算されたシステムが同時に開くことができるファイル数の最大値です。通常、ソフト制限はハード制限以下です。

上記の制限を変更する最も簡単な方法はulimitコマンドを使用することです:

[speng@as4 ~]$ ulimit -n

上記のコマンドで、[number]には設定したい単一プロセスが開くことができる最大ファイル数を指定します。システムが「Operation not permitted」のようなメッセージを表示する場合、上記の制限の変更に失敗したことを意味します。実際には、[number]で指定した数値がLinuxシステムのそのユーザーのファイルオープン数のソフト制限またはハード制限を超えているためです。したがって、Linuxシステムのユーザーのファイルオープン数に関するソフト制限とハード制限を変更する必要があります。

第一步、/etc/security/limits.confファイルを変更し、ファイルに以下の行を追加します:

speng soft nofile 10240
speng hard nofile 10240

ここで、spengはどのユーザーのファイルオープン数制限を変更するかを指定し、*記号を使用してすべてのユーザーの制限を変更することもできます。softまたはhardはソフト制限とハード制限のどちらを変更するかを指定し、10240は変更したい新しい制限値、つまり最大オープンファイル数を指定します(ソフト制限値はハード制限以下である必要があります)。変更後、ファイルを保存します。

第二步、/etc/pam.d/loginファイルを変更し、ファイルに以下の行を追加します:

session required /lib/security/pam_limits.so

これはユーザーがシステムログインを完了した後、Linuxがpam_limits.soモジュールを呼び出してシステムがそのユーザーが使用できる各リソースの最大数量を設定するように指示します(ユーザーが開くことができる最大ファイル数制限を含む)。そして、pam_limits.soモジュールは/etc/security/limits.confファイルから設定を読み取ってこれらの制限値を設定します。変更後、このファイルを保存します。

第三步、Linuxシステムレベルの最大オープンファイル数制限を確認するには、以下のコマンドを使用します:

[speng@as4 ~]$ cat /proc/sys/fs/file-max

12158

これはこのLinuxシステムが最大12158個のファイルを同時に開くことを許可していることを示しています(すべてのユーザーが開くファイル数の合計)。これはLinuxシステムレベルのハード制限であり、すべてのユーザーレベルのオープンファイル数制限はこの数値を超えてはなりません。通常、このシステムレベルのハード制限はLinuxシステムが起動時にシステムのハードウェアリソース状況に基づいて計算された最適の最大同時オープンファイル数制限です。特別な必要がない限り、この制限を変更すべきではありません。ユーザーレベルのオープンファイル数制限にこの制限を超える値を設定したい場合を除きます。このハード制限を変更する方法は/etc/rc.localスクリプトを変更し、スクリプトに以下の行を追加することです:

echo 22158 > /proc/sys/fs/file-max

これはLinuxが起動完了後にシステムレベルのオープンファイル数ハード制限を22158に強制設定するようにします。変更後、ファイルを保存します。

上記の手順を完了した後、システムを再起動します。通常、これによりLinuxシステムが指定されたユーザーの単一プロセスが同時に開くことができる最大ファイル数制限を指定された値に設定できます。再起動後もulimit -nコマンドでユーザーのオープンファイル数制限が上記の手順で設定した最大値より低い場合、これはユーザーログインスクリプト/etc/profileでulimit -nコマンドがユーザーが同時に開くことができる最大ファイル数を既に制限している可能性があります。ulimit -nを使用してシステムがユーザーが同時に開くことができる最大ファイル数制限を変更する場合、新しく変更した値は前回のulimit -n設定値以下である必要があるため、このコマンドを使用してこの制限値を増やすことはできません。したがって、上記の問題が存在する場合、/etc/profileスクリプトファイルを開き、ファイル内でulimit -nがユーザーが同時に開くことができる最大ファイル数を制限しているかどうかを検索し、見つかった場合はこのコマンド行を削除するか、設定値を適切な値に変更し、ファイルを保存してユーザーをシステムからログアウトし、再ログインする必要があります。

上記の手順を通じて、高並発TCP接続処理をサポートする通信処理プログラムについて、ファイルオープン数に関するシステム制限を解除しました。

2、ネットワークカーネルのTCP接続に関する制限を変更する

Linux上で高並発TCP接続をサポートするクライアント通信処理プログラムを記述する場合、システムがユーザーが同時に開くファイル数の制限を解除したにもかかわらず、並発TCP接続数が一定の数に増加すると、新しいTCP接続を正常に確立できなくなることがあります。この現象にはいくつかの原因があります。

第一の原因は、Linuxネットワークカーネルがローカルポート番号の範囲に制限があるためです。この場合、なぜTCP接続を確立できないかをさらに分析すると、問題がconnect()呼び出しの失敗にあり、システムエラーメッセージが「Can't assign requested address」であることがわかります。同時に、この時にtcpdumpツールを使用してネットワークを監視すると、クライアントがSYNパケットを送信するネットワークトラフィックが全くないことがわかります。これらの状況は、ローカルLinuxシステムカーネルに制限があることを示しています。問題の根本原因は、LinuxカーネルのTCP/IPプロトコル実装モジュールがシステム内のすべてのクライアントTCP接続に対応するローカルポート番号の範囲を制限しているためです(例えば、カーネルはローカルポート番号の範囲を1024~32768に制限しています)。システム内のある時点で同時に多くのクライアントTCP接続が存在する場合、各クライアントTCP接続はシステムのローカルポート番号範囲制限内で一意のローカルポート番号を占有する必要があります(このポート番号はシステムのローカルポート番号範囲制限内)。既存のクライアントTCP接続ですでにすべてのローカルポート番号を使用している場合、新しいクライアントTCP接続にローカルポート番号を割り当てることができなくなり、システムはこの状況でconnect()呼び出しに失敗を返し、エラーメッセージを「Can't assign requested address」に設定します。これらの制御ロジックについては、Linuxカーネルソースコードを参照できます。linux2.6カーネルを例に、tcp_ipv4.cファイルの以下の関数を参照してください:

static int tcp_v4_hash_connect(struct sock *sk)

上記の関数内での変数sysctl_local_port_rangeへのアクセス制御に注意してください。変数sysctl_local_port_rangeの初期化はtcp.cファイルの以下の関数で設定されています:

void __init tcp_init(void)

カーネルコンパイル時のデフォルト設定のローカルポート番号範囲は小さすぎる可能性があるため、このローカルポート範囲制限を変更する必要があります。

第一步、/etc/sysctl.confファイルを変更し、ファイルに以下の行を追加します:

net.ipv4.ip_local_port_range = 1024 65000

これはシステムのローカルポート範囲制限を1024~65000に設定することを示します。ローカルポート範囲の最小値は1024以上である必要があり、ポート範囲の最大値は65535以下である必要があります。変更後、このファイルを保存します。

第二步、sysctlコマンドを実行します:

[speng@as4 ~]$ sysctl -p

システムにエラーメッセージが表示されなければ、新しいローカルポート範囲の設定は成功したことを意味します。上記のポート範囲で設定する場合、理論上単一のプロセスで最大60000以上のTCPクライアント接続を同時に確立できます。

第二のTCP接続を確立できない原因は、LinuxネットワークカーネルのIP_TABLEファイアウォールが追跡する最大TCP接続数に制限がある可能性があります。この場合、プログラムはconnect()呼び出しでブロックし、まるでフリーズしたかのように見えます。tcpdumpツールを使用してネットワークを監視しても、クライアントがSYNパケットを送信するネットワークトラフィックが全くないことがわかります。IP_TABLEファイアウォールはカーネル内で各TCP接続の状態を追跡し、追跡情報はカーネルメモリ内のconntrackデータベースに保存されます。このデータベースのサイズには限りがあり、システム内に多くのTCP接続が存在するとデータベースの容量が不足し、IP_TABLEが新しいTCP接続の追跡情報を確立できなくなり、connect()呼び出しでブロックするように見えます。この場合、カーネルが追跡する最大TCP接続数の制限を変更する必要があり、その方法はカーネルのローカルポート番号範囲の制限を変更する方法と似ています:

第一步、/etc/sysctl.confファイルを変更し、ファイルに以下の行を追加します:

net.ipv4.ip_conntrack_max = 10240

これはシステムが追跡する最大TCP接続数の制限を10240に設定することを示します。この制限値は、カーネルメモリの使用を節約するためにできるだけ小さくする必要があります。

第二步、sysctlコマンドを実行します:

[speng@as4 ~]$ sysctl -p

システムにエラーメッセージが表示されなければ、システムの新しい最大追跡TCP接続数制限の変更は成功したことを意味します。上記のパラメータで設定する場合、理論上単一のプロセスで最大10000以上のTCPクライアント接続を同時に確立できます。

*******注意*******
sysctl -pがエラーを報告し「net.ipv4.ip_conntrack_max」は未知のキーである場合は:modprobe ip_conntrack

タグ: linux ulimit システムリソース制限 ファイルディスクリプタ 高並発

6月5日 16:51 投稿