Do you know how to modify the value of “max open files” for a running process? You can modify that it is using the command “prlimit”(You can also modify more than just “max open files”).

docker-prlimit-example makes it easy to try.
Run the following commands in order to connect to the docker container where the unicorn process is running.

$ 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

Let’s run ps, you can see that the unicorn process is running.

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

Now, try to modify “max open files” using prlimit.
First, let’s run the following command to check the current value.

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

The NOFILE line is the “max open files”.The soft limit / hard limit are both set to 1048576.
Modify the value of soft limit / hard limit to 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

You can see that the value has changed to 1024.

Forking a process like a unicorn does not affect child processes. The following command generates a prlimit command that modifies the “max open files” for both the parent and child processes.

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 is the PID of the parent process, and PID=10,13 are the child processes. Why not just run prlimit directly? This is because prlimit has a large impact when it fails, and I think it’s better to check it before running. For example, if you mistakenly use –nofile=1:1, the process will most likely not work properly. If you only need to modify the child processes, please run the following command.

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

Conclusion

This article was an introduction to how to use prlimit to modify the value of “max open files”.
I hope this helps you!