実行中のプロセスの 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

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

では、実際に 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

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

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

上記の例では、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
comment

Comments

arrow_back

Previous

embulk の resume-state と config-diff の検証結果

Next

CircleCI の workflows の branch フィルタは ignore と only を同時に指定できない
arrow_forward