サーバーやコンピュータを使っていて、こんな経験はありませんか?
- プログラムが暴走して、システム全体が重くなってしまった
 - 「開けるファイルが多すぎます」というエラーが出た
 - あるアプリケーションがメモリを使い切ってしまった
 
こうした問題を防ぐために、LinuxやUNIXシステムにはリソース制限という仕組みがあります。
その中でも重要なのが、ハードリミット(Hard Limit)とソフトリミット(Soft Limit)です。
この記事では、この2つのリミットの違いや設定方法について、初心者の方にも分かるように詳しく解説していきます。サーバー管理者やプログラマーにとって、知っておくべき重要な知識です。
リソース制限って何?なぜ必要なの?

リソース制限の基本
リソース制限とは、プログラムやユーザーが使えるシステムリソース(資源)の上限を設定する仕組みです。
主なリソースの種類:
- ファイル記述子:同時に開けるファイルの数
 - プロセス数:同時に起動できるプロセス(プログラム)の数
 - メモリ:使用できるメモリの量
 - CPU時間:CPUを使える時間
 - ファイルサイズ:作成できるファイルの最大サイズ
 
なぜリソース制限が必要なのか?
リソース制限がないと、大変なことになります。
問題1:システム全体のダウン
- あるプログラムがメモリを使い切る
 - 他のプログラムが動かなくなる
 - システム全体がフリーズ
 
問題2:他のユーザーへの影響
- 一人のユーザーがリソースを独占
 - 他のユーザーが作業できなくなる
 - 共有サーバーで深刻な問題に
 
問題3:セキュリティリスク
- 悪意あるプログラムが無限にプロセスを生成
 - フォーク爆弾(Fork Bomb)などの攻撃
 - システムが使用不能に
 
問題4:予期せぬ障害
- プログラムのバグで無限ループ
 - ファイルが際限なく大きくなる
 - ディスク容量を使い切る
 
日常的な例で理解する
分かりやすく例えると、リソース制限は「レストランの席数制限」のようなものです。
リソース制限がない場合:
- 一つのグループが全席を占領
 - 他のお客さんが入れない
 - レストランが機能しなくなる
 
リソース制限がある場合:
- 一つのグループに予約できる席数の上限を設定
 - 他のお客さんも利用できる
 - 全体がスムーズに機能する
 
システムも同じで、適切な制限があることで、安定して動作できるわけです。
ハードリミットとソフトリミットの基本
LinuxやUNIXのリソース制限には、2つのレベルがあります。
ソフトリミット(Soft Limit)
ソフトリミットは、通常適用される制限です。
特徴:
- プログラムやユーザーが通常守るべき上限
 - 自分で変更できる(ただしハードリミットまで)
 - 警告的な意味合いが強い
 - 超えるとエラーが発生する
 
イメージ:
「制限速度60km/h」のような、日常的に守るべき制限です。
ハードリミット(Hard Limit)
ハードリミットは、絶対に超えられない上限です。
特徴:
- システムが許可する最大値
 - 一般ユーザーは引き上げられない
 - root(管理者)だけが変更できる
 - 絶対的な天井
 
イメージ:
「この道路は物理的に幅5メートル」のような、変更できない物理的な限界です。
2つの関係性
ソフトリミットとハードリミットには、明確な関係があります。
ルール:
0 ≦ ソフトリミット ≦ ハードリミット
つまり:
- ソフトリミットは、ハードリミット以下でなければならない
 - ソフトリミットは、いつでもハードリミットの範囲内で調整できる
 - ハードリミットを超えることは、root以外には不可能
 
具体例で理解する
ファイル記述子(同時に開けるファイル数)の例を見てみましょう。
設定例:
- ソフトリミット: 1024
 - ハードリミット: 4096
 
動作:
- 通常は1024個までファイルを開ける
 - プログラムは自分でソフトリミットを2048に変更できる
 - ただし4096を超えることはできない
 - root権限があれば、ハードリミット自体を変更可能
 
なぜ2段階なの?
2段階に分かれている理由は、柔軟性とセキュリティのバランスです。
ソフトリミットの役割:
- 通常時は低い値で安全に運用
 - 必要に応じてプログラムが自分で引き上げられる
 - ユーザーが一時的に調整できる
 
ハードリミットの役割:
- システムの安定性を守る最後の砦
 - 管理者が管理する
 - 無制限な使用を防ぐ
 
この組み合わせにより、使いやすさと安全性を両立できるわけです。
リソース制限の種類
LinuxやUNIXで制限できるリソースは、多岐にわたります。
1. RLIMIT_NOFILE(ファイル記述子数)
意味:
同時に開けるファイルの最大数
なぜ重要?
- Webサーバーは多数の接続を同時に処理する
 - 各接続でファイル記述子を使用
 - 制限が低いと「Too many open files」エラーが発生
 
典型的な値:
- ソフトリミット: 1024
 - ハードリミット: 4096〜65536
 
用途:
- Apache、NginxなどのWebサーバー
 - データベースサーバー
 - ネットワークアプリケーション
 
2. RLIMIT_NPROC(プロセス数)
意味:
ユーザーが作成できるプロセスの最大数
なぜ重要?
- フォーク爆弾(無限にプロセスを生成する攻撃)を防ぐ
 - システムリソースの枯渇を防止
 
典型的な値:
- ソフトリミット: 1024〜4096
 - ハードリミット: 2048〜16384
 
注意点:
ユーザー単位の制限なので、そのユーザーの全プロセスの合計が対象です。
3. RLIMIT_FSIZE(ファイルサイズ)
意味:
作成できるファイルの最大サイズ
なぜ重要?
- ログファイルが無限に大きくなるのを防ぐ
 - ディスク容量の枯渇を防止
 
典型的な値:
- unlimitedに設定されることが多い
 - 必要に応じて制限を設ける
 
4. RLIMIT_DATA(データセグメントサイズ)
意味:
プロセスのデータ領域の最大サイズ
用途:
メモリ使用量の制限(ただし、現代のシステムではあまり使われない)
5. RLIMIT_STACK(スタックサイズ)
意味:
プロセスのスタック領域の最大サイズ
なぜ重要?
- 再帰呼び出しが深すぎる場合のクラッシュを防ぐ
 - スタックオーバーフローの制御
 
典型的な値:
- 8192 KB(8 MB)
 
6. RLIMIT_AS(仮想メモリサイズ)
意味:
プロセスが使用できる仮想メモリの合計サイズ
なぜ重要?
- メモリリークしたプログラムがシステム全体のメモリを消費するのを防ぐ
 
7. RLIMIT_CPU(CPU時間)
意味:
プロセスが使用できるCPU時間の上限(秒単位)
なぜ重要?
- 無限ループなどで永遠にCPUを使い続けるのを防ぐ
 
動作:
制限に達すると、プロセスにSIGXCPUシグナルが送られます。
8. RLIMIT_CORE(コアダンプサイズ)
意味:
コアダンプファイルの最大サイズ
用途:
- デバッグ時にコアダンプを許可
 - 本番環境では0に設定してディスク容量を節約
 
9. RLIMIT_MEMLOCK(ロックできるメモリサイズ)
意味:
物理メモリにロック(固定)できるメモリの量
用途:
- リアルタイムアプリケーション
 - セキュリティが重要なデータの保護
 
10. RLIMIT_LOCKS(ファイルロック数)
意味:
設定できるファイルロックの最大数
用途:
データベースなどで複数プロセスがファイルにアクセスする場合
リソース制限の確認方法

現在のリソース制限を確認する方法を見ていきましょう。
ulimitコマンド
ulimitは、シェルからリソース制限を確認・設定するコマンドです。
すべての制限を表示:
ulimit -a
出力例:
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15390
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) 15390
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
ソフトリミットとハードリミットを別々に確認
ソフトリミットを表示:
ulimit -S -a
ハードリミットを表示:
ulimit -H -a
特定のリソースだけ確認
ファイル記述子数を確認:
ulimit -n
プロセス数を確認:
ulimit -u
スタックサイズを確認:
ulimit -s
/proc ファイルシステムで確認
特定のプロセスの制限を確認できます。
プロセスID 1234 の制限を確認:
cat /proc/1234/limits
出力例:
Limit                     Soft Limit           Hard Limit           Units
Max cpu time              unlimited            unlimited            seconds
Max file size             unlimited            unlimited            bytes
Max data size             unlimited            unlimited            bytes
Max stack size            8388608              unlimited            bytes
Max core file size        0                    unlimited            bytes
Max resident set          unlimited            unlimited            bytes
Max processes             15390                15390                processes
Max open files            1024                 4096                 files
Max locked memory         65536                65536                bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       15390                15390                signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us
この表示なら、ソフトリミットとハードリミットの両方が一目で分かります。
リソース制限の設定方法
リソース制限を変更する方法を見ていきましょう。
ulimitコマンドで一時的に変更
ソフトリミットを変更:
ulimit -n 2048
これで、現在のシェルセッションでファイル記述子数が2048に増えます。
注意点:
- 変更は現在のシェルとその子プロセスにのみ有効
 - シェルを閉じると元に戻る
 - ハードリミットを超える値には設定できない
 
ハードリミットを変更(root権限が必要):
sudo ulimit -H -n 4096
/etc/security/limits.conf で永続的に設定
システム全体またはユーザー・グループ単位で、恒久的に制限を設定できます。
ファイルの場所:
/etc/security/limits.conf
基本的な書式:
<ドメイン> <タイプ> <アイテム> <値>
パラメータの説明:
ドメイン:
- ユーザー名(例:
john) - グループ名(例:
@developers) *(すべてのユーザー)
タイプ:
soft:ソフトリミットhard:ハードリミット-:両方同時に設定
アイテム:
nofile:ファイル記述子数(RLIMIT_NOFILE)nproc:プロセス数(RLIMIT_NPROC)fsize:ファイルサイズ(RLIMIT_FSIZE)core:コアダンプサイズ(RLIMIT_CORE)stack:スタックサイズ(RLIMIT_STACK)- その他多数
 
設定例:
例1:すべてのユーザーのファイル記述子数を増やす
*    soft    nofile    2048
*    hard    nofile    4096
例2:特定ユーザーのプロセス数を制限
john    soft    nproc    1024
john    hard    nproc    2048
例3:グループ単位での設定
@developers    soft    nofile    4096
@developers    hard    nofile    8192
例4:複数の制限をまとめて設定
mysql    soft    nofile    10240
mysql    hard    nofile    10240
mysql    soft    nproc     2048
mysql    hard    nproc     2048
設定の反映:
- 新しいログインセッションから有効になる
 - 既存のセッションには影響しない
 - 再ログインまたは 
su - ユーザー名で反映 
systemdサービスでの設定
systemdで管理されるサービスでは、サービスファイルで制限を設定できます。
サービスファイルの例:
[Service]
LimitNOFILE=10240
LimitNPROC=2048
LimitCORE=0
設定できる項目:
LimitNOFILE:ファイル記述子数LimitNPROC:プロセス数LimitCORE:コアダンプサイズLimitCPU:CPU時間LimitAS:仮想メモリサイズ- その他
 
反映方法:
sudo systemctl daemon-reload
sudo systemctl restart サービス名
PAM(Pluggable Authentication Modules)の設定
limits.confは、実際にはPAMモジュール pam_limits.so によって読み込まれます。
PAM設定ファイル:
/etc/pam.d/common-session
設定行(通常は既に含まれている):
session required pam_limits.so
この行がないと、limits.confの設定が有効になりません。
プログラムからリソース制限を操作する
プログラム内から、リソース制限を取得・設定できます。
C言語での操作
関数:
getrlimit():リソース制限を取得setrlimit():リソース制限を設定
ヘッダーファイル:
#include <sys/resource.h>
基本的な使い方:
#include <stdio.h>
#include <sys/resource.h>
int main() {
    struct rlimit limit;
    // ファイル記述子数の制限を取得
    if (getrlimit(RLIMIT_NOFILE, &limit) == 0) {
        printf("ソフトリミット: %ld\n", limit.rlim_cur);
        printf("ハードリミット: %ld\n", limit.rlim_max);
    }
    // ソフトリミットを変更(ハードリミットの範囲内)
    limit.rlim_cur = 2048;
    if (setrlimit(RLIMIT_NOFILE, &limit) == 0) {
        printf("ソフトリミットを2048に変更しました\n");
    } else {
        perror("setrlimit");
    }
    return 0;
}
構造体 rlimit:
struct rlimit {
    rlim_t rlim_cur;  /* ソフトリミット */
    rlim_t rlim_max;  /* ハードリミット */
};
リソースの種類(第1引数):
RLIMIT_NOFILE:ファイル記述子数RLIMIT_NPROC:プロセス数RLIMIT_FSIZE:ファイルサイズRLIMIT_CPU:CPU時間RLIMIT_AS:仮想メモリサイズ- その他
 
Pythonでの操作
モジュール:
import resource
基本的な使い方:
import resource
# ファイル記述子数の制限を取得
soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
print(f"ソフトリミット: {soft}")
print(f"ハードリミット: {hard}")
# ソフトリミットを変更
resource.setrlimit(resource.RLIMIT_NOFILE, (2048, hard))
print("ソフトリミットを2048に変更しました")
リソース定数:
resource.RLIMIT_NOFILEresource.RLIMIT_NPROCresource.RLIMIT_FSIZEresource.RLIMIT_CPUresource.RLIMIT_AS
実践的な使用例
Webサーバーの起動時に制限を引き上げる:
import resource
import sys
def increase_file_descriptors():
    try:
        soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
        print(f"現在の制限: soft={soft}, hard={hard}")
        # ハードリミットの80%まで引き上げる
        new_soft = int(hard * 0.8)
        resource.setrlimit(resource.RLIMIT_NOFILE, (new_soft, hard))
        soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
        print(f"新しい制限: soft={soft}, hard={hard}")
    except ValueError as e:
        print(f"エラー: {e}")
        sys.exit(1)
if __name__ == "__main__":
    increase_file_descriptors()
    # この後、サーバーのメイン処理を開始
よくある問題とトラブルシューティング
問題1:「Too many open files」エラー
症状:
プログラムがファイルを開こうとするとエラーが発生
原因:
ファイル記述子の制限(RLIMIT_NOFILE)に達した
解決方法:
一時的な対処:
ulimit -n 4096
恒久的な対処:/etc/security/limits.conf に追加:
*    soft    nofile    4096
*    hard    nofile    8192
systemdサービスの場合:
サービスファイルに追加:
[Service]
LimitNOFILE=8192
問題2:ulimitの変更が反映されない
症状:
limits.confを編集したのに、制限が変わらない
原因と対策:
原因1:再ログインしていない
- 新しいセッションでログインし直す
 - または 
su - ユーザー名で再ログイン 
原因2:PAMモジュールが有効になっていない
/etc/pam.d/common-sessionを確認session required pam_limits.soの行があるか確認
原因3:systemdサービスでlimits.confが効かない
- systemdサービスは独自の制限を持つ
 - サービスファイルで 
LimitNOFILEなどを設定 
原因4:ハードリミット以上に設定しようとしている
- まずハードリミットを引き上げる必要がある
 - root権限が必要
 
問題3:プロセスが起動できない
症状:
「Resource temporarily unavailable」エラー
原因:
プロセス数の制限(RLIMIT_NPROC)に達した
確認方法:
# 現在のプロセス数制限を確認
ulimit -u
# 実際のプロセス数を確認
ps -u ユーザー名 | wc -l
解決方法:
limits.confで制限を引き上げる:
ユーザー名    soft    nproc    4096
ユーザー名    hard    nproc    8192
問題4:コアダンプが生成されない
症状:
プログラムがクラッシュしてもコアダンプファイルが作られない
原因:
コアダンプサイズの制限が0に設定されている
確認方法:
ulimit -c
解決方法:
# 無制限に設定
ulimit -c unlimited
恒久的な設定:
limits.confに追加:
*    soft    core    unlimited
*    hard    core    unlimited
注意:
コアダンプファイルは大きくなることがあるので、本番環境では慎重に設定してください。
問題5:Webサーバーが接続を拒否する
症状:
高負荷時にWebサーバーが新しい接続を受け付けない
原因:
ファイル記述子の不足
解決方法:
1. 現在の使用状況を確認:
lsof -u www-data | wc -l
2. 制限を確認:
sudo -u www-data bash -c 'ulimit -n'
3. Nginxの場合、設定ファイルで調整:
worker_rlimit_nofile 8192;
events {
    worker_connections 4096;
}
4. systemdサービスで制限を引き上げ:
[Service]
LimitNOFILE=8192
ベストプラクティス
リソース制限を効果的に使うためのベストプラクティスです。
1. 適切な値の設定
基本的な考え方:
- 低すぎる制限:正常な動作を妨げる
 - 高すぎる制限:リソースの枯渇を防げない
 - 適切なバランスが重要
 
推奨される設定例:
一般的なWebサーバー:
*    soft    nofile    4096
*    hard    nofile    8192
*    soft    nproc     2048
*    hard    nproc     4096
高負荷なデータベースサーバー:
mysql    soft    nofile    10240
mysql    hard    nofile    10240
mysql    soft    nproc     4096
mysql    hard    nproc     4096
2. 段階的な引き上げ
いきなり大きな値に設定するのではなく、段階的に調整します。
手順:
- 現在の使用状況を監視
 - 制限に達する前に引き上げ
 - 様子を見ながら再調整
 - 必要十分な値を見つける
 
3. 監視とログ
リソース制限に関するエラーを監視します。
監視項目:
- 「Too many open files」エラーの発生
 - プロセス起動失敗の頻度
 - リソース使用量の推移
 
ログの確認:
# システムログでエラーを検索
grep "Too many open files" /var/log/syslog
grep "Resource temporarily unavailable" /var/log/syslog
4. サービスごとに個別設定
すべてのユーザーに高い制限を与えるのではなく、必要なサービスにのみ設定します。
良い例:
# Webサーバー用
nginx    soft    nofile    8192
nginx    hard    nofile    8192
# データベース用
mysql    soft    nofile    10240
mysql    hard    nofile    10240
# 一般ユーザーは控えめに
*        soft    nofile    1024
*        hard    nofile    4096
5. ハードリミットに余裕を持たせる
ソフトリミットとハードリミットの間に余裕を持たせます。
理由:
- プログラムが必要に応じてソフトリミットを引き上げられる
 - 緊急時の対応余地を残す
 
例:
*    soft    nofile    2048
*    hard    nofile    4096
6. ドキュメント化
設定の理由と値を記録しておきます。
limits.conf にコメントを追加:
# Nginxの最大接続数に合わせて設定(2024-01-15)
nginx    soft    nofile    8192
nginx    hard    nofile    8192
7. テスト環境で検証
本番環境に適用する前に、テスト環境で動作確認します。
確認項目:
- アプリケーションが正常に動作するか
 - パフォーマンスに問題はないか
 - 予期せぬエラーが発生しないか
 
8. セキュリティの観点
リソース制限は、セキュリティ対策の一環でもあります。
考慮点:
- 攻撃者がリソースを使い切れないようにする
 - フォーク爆弾などの攻撃を防ぐ
 - 一般ユーザーには必要最小限の権限を与える
 
まとめ:ハードリミットとソフトリミットで安定したシステムを
ハードリミットとソフトリミットは、Linuxシステムのリソースを適切に管理するための重要な仕組みです。
この記事のポイント:
- リソース制限の目的:システムの安定性を保ち、リソースの枯渇を防ぐ
 - ソフトリミット:通常適用される制限で、ユーザーが変更できる
 - ハードリミット:絶対的な上限で、root権限がないと変更できない
 - 2段階の理由:柔軟性とセキュリティのバランスを取るため
 - 主な種類:ファイル記述子数、プロセス数、メモリ、CPU時間など
 - 確認方法:ulimit コマンドや /proc ファイルシステム
 - 設定方法:ulimit(一時的)、limits.conf(恒久的)、systemdサービスファイル
 - プログラムからの操作:getrlimit()、setrlimit() などのシステムコール
 - よくある問題:「Too many open files」エラーへの対処
 - ベストプラクティス:適切な値の設定、監視、サービスごとの個別設定
 
サーバー管理者やプログラマーにとって、リソース制限の理解は必須です。
適切に設定することで:
- システムの安定性が向上する
 - 予期せぬ障害を防げる
 - セキュリティリスクを減らせる
 - アプリケーションのパフォーマンスを最適化できる
 
特に、Webサーバーやデータベースなど、多くのリソースを使うアプリケーションを運用する場合は、リソース制限の調整が重要になります。
まずは現在の設定を確認し、アプリケーションの要件に合わせて適切に調整してみましょう。システムの安定性とパフォーマンスが向上するはずです。
  
  
  
  
              
              
              
              
              

コメント