実行中のプロセスの max open files の値を変更する

実行中のプロセスの max open files の値を変更する prlimit というコマンドがあります(max open files 以外も変更できます)。

https://github.com/tkuchiki/docker-prlimit-example で試せる環境を用意して動作検証しました。
以下のコマンドを順に実行すると、unicorn のプロセスが起動している docker container に接続できます。

$ git clone https://github.com/tkuchiki/docker-prlimit-example $ cd docker-prlimit-example $ docker build -t prlimit . $ docker run -d --rm prlimit $ docker exec -it $(docker ps | grep prlimit | awk '{print $1}') bash
Code language: JavaScript (javascript)

ps を実行してみると、unicorn のプロセスが動いていることを確認できます。

root@b83fe16b540e:/app# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 1.2 1.1 102084 23336 ? Ssl 04:03 0:00 unicorn master -c unicorn_config.rb -E development -d -l0.0.0.0:8080 root 10 0.0 0.9 102084 19436 ? Sl 04:03 0:00 unicorn worker[0] -c unicorn_config.rb -E development -d -l0.0.0.0:8080 root 13 0.0 0.9 102084 19044 ? Sl 04:03 0:00 unicorn worker[1] -c unicorn_config.rb -E development -d -l0.0.0.0:8080 root 16 4.3 0.1 18500 3348 pts/0 Ss 04:04 0:00 bash root 27 0.0 0.1 34396 2732 pts/0 R+ 04:04 0:00 ps aux
Code language: PHP (php)

では、実際に prlimit を使って max open files を変更していきます。
まず、現在の値を確認するには以下を実行します。

root@b83fe16b540e:/app# prlimit --pid 1 RESOURCE DESCRIPTION SOFT HARD UNITS AS address space limit unlimited unlimited bytes CORE max core file size 0 unlimited bytes CPU CPU time unlimited unlimited seconds DATA max data size unlimited unlimited bytes FSIZE max file size unlimited unlimited bytes LOCKS max number of file locks held unlimited unlimited locks MEMLOCK max locked-in-memory address space 83968000 83968000 bytes MSGQUEUE max bytes in POSIX mqueues 819200 819200 bytes NICE max nice prio allowed to raise 0 0 NOFILE max number of open files 1048576 1048576 files NPROC max number of processes unlimited unlimited processes RSS max resident set size unlimited unlimited bytes RTPRIO max real-time priority 0 0 RTTIME timeout for real-time tasks unlimited unlimited microsecs SIGPENDING max number of pending signals 7862 7862 signals STACK max stack size 8388608 unlimited bytes
Code language: PHP (php)

NOFILE の行が max open files です。soft limit / hard limit ともに 1048576 になっています。

(実際のオペレーションで値を下げることはあまりないかもしれませんが) soft limit / hard limit の値を 1024 に変更します。

root@b83fe16b540e:/app# prlimit --pid 1 --nofile=1024:1024 root@b83fe16b540e:/app# prlimit --pid 1 RESOURCE DESCRIPTION SOFT HARD UNITS AS address space limit unlimited unlimited bytes CORE max core file size 0 unlimited bytes CPU CPU time unlimited unlimited seconds DATA max data size unlimited unlimited bytes FSIZE max file size unlimited unlimited bytes LOCKS max number of file locks held unlimited unlimited locks MEMLOCK max locked-in-memory address space 83968000 83968000 bytes MSGQUEUE max bytes in POSIX mqueues 819200 819200 bytes NICE max nice prio allowed to raise 0 0 NOFILE max number of open files 1024 1024 files NPROC max number of processes unlimited unlimited processes RSS max resident set size unlimited unlimited bytes RTPRIO max real-time priority 0 0 RTTIME timeout for real-time tasks unlimited unlimited microsecs SIGPENDING max number of pending signals 7862 7862 signals STACK max stack size 8388608 unlimited bytes
Code language: PHP (php)

1024 に変わっていることが確認できます。
このとき、unicorn のようにプロセスを fork している場合、子プロセスには反映されません(同じプロセスではないので当然ですね)。
以下のようなワンライナーを実行すると prlimit コマンドを生成できます。

root@b83fe16b540e:/app# PID=1; pids(){ echo $1; for p in $(ps --ppid $1 --no-heading | awk '{ print $1 }'); do echo $p; pids $p ; done ; }; pids $PID | uniq | xargs -I{} echo "prlimit --pid {} --nofile=65536:65536" prlimit --pid 1 --nofile=65536:65536 prlimit --pid 10 --nofile=65536:65536 prlimit --pid 13 --nofile=65536:65536
Code language: PHP (php)

上記の例では、PID=1 が親プロセスの PID で、PID = 10, 13 が子プロセスです。
PID で指定したプロセスとその子プロセス分の prlimit コマンドを生成しています。
わざわざいきなり xargs で prlimit を実行していないのは、prlimit は失敗したときの影響が大きいので、確認できるようにするためです。
たとえば、間違えて –nofile=1:1 のようにしてしまった場合、ほとんどの場合プロセスが正常に動作しなくなるでしょう。
親プロセスは変更しなく良い場合は以下のワンライナーで OK です。

root@b83fe16b540e:/app# PID=1; pids(){ for p in $(ps --ppid $1 --no-heading | awk '{ print $1 }'); do echo $p; pids $p ; done ; }; pids $PID | xargs -I{} echo "prlimit --pid {} --nofile=65536:65536" prlimit --pid 10 --nofile=65536:65536 prlimit --pid 13 --nofile=65536:65536
Code language: PHP (php)

Leave a Reply