Project

General

Profile

Actions

Fix "too many open files" for SystemD managed service

Synopsis

For processes that are spawned normally (like your shell), the maximum number of open file handles is configured through /etc/security/limits.conf and files in /etc/security/limits.d/.

SystemD being what it is, completely ignores these settings and uses its own configuration, falling back to (what it considers) reasonable defaults if no explicit limits are set.

This means that to increase limits for services that are started by SystemD, you'll need to edit the .service file of the service.

Terminology

There are two kinds of limits: soft limits and hard limits:
  • hard limit: the upper limit for a given resource. This cannot be increased (unless you're root)
  • soft limit: the current limit for a given resource. Can be increased up to the hard limit

Attribution

The guide at https://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/ helped me to figure out how to do this.

Checking current limits

System-wide limit

The upper limit (for file handles) imposed by the kernel can not be exceeded.

Check it with:

# cat /proc/sys/fs/file-max
9223372036854775807

That's plenty :)

The limits of a specific process

I used ps auxww | grep <processname> to get the PID of the process I was interested in.

With the PID, we can check the limits for that process:

# cat /proc/2315036/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             128309               128309               processes
Max open files            1024                 524288               files
Max locked memory         65536                65536                bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       128309               128309               signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us

So we see that the soft limit is 1024, which is a bit on the low side. Let's increase it to 4096.

Increasing the limit for open files

List of limits that can be changed

SystemD allows to specify limits in a .service file.

These are the limits that can be specified:
  • LimitCPU
  • LimitFSIZE
  • LimitDATA
  • LimitSTACK
  • LimitCORE
  • LimitRSS
  • LimitNOFILE
  • LimitAS
  • LimitNPROC
  • LimitMEMLOCK
  • LimitLOCKS
  • LimitSIGPENDING
  • LimitMSGQUEUE
  • LimitNICE
  • LimitRTPRIO
  • LimitRTTIME

We are interested in LimitNOFILE.

See the systemd.exec(5) manpage for more information.

Change the limit

Instead of directly editing the .service file, we'll use a so-called systemd drop-in. This keeps the original .service file intact (which is greatly appreciated by your package manager), but allows for selective overriding of settings from that original file.

NOTE: For some reason SystemD uses nano as its default editor. If you want to use vim, you can do that by executing export EDITOR=vim before executing the command below.

Execute systemctl edit <service-name>.service (in my case the service is zabbix-agent2) to open an editor with the override file and add the lines in yellow:

### Editing /etc/systemd/system/zabbix-agent2.service.d/override.conf
### Anything between here and the comment below will become the new contents of the file

[Service]
LimitNOFILE=4096
### Lines below this comment will be discarded ### /lib/systemd/system/zabbix-agent2.service # [Unit] # Description=Zabbix Agent 2 # After=syslog.target # After=network.target # # [Service] # Environment="CONFFILE=/etc/zabbix/zabbix_agent2.conf" # EnvironmentFile=-/etc/default/zabbix-agent2 # Type=simple # Restart=on-failure # PIDFile=/run/zabbix/zabbix_agent2.pid # KillMode=control-group # ExecStart=/usr/sbin/zabbix_agent2 -c $CONFFILE # ExecStop=/bin/kill -SIGTERM $MAINPID # RestartSec=10s # User=zabbix # Group=zabbix # # [Install] # WantedBy=multi-user.target

You can leave the commented out stuff as it is, it gives you a bit of context with the contents of the original .service file.

NOTE: Don't forget to add the [Service] header! If you don't, you will get no error, but it won't work. Ask me how I know…

Restart the service

After saving and quitting the editor, there is no need to explicitly execute systemctl daemon-reload. Because the editing was done through a systemd mechanism, that is taken care of automatically.

Restart the service: systemctl restart zabbix-agent2.service.

Get the PID of the restarted process and check its limits:

# cat /proc/2333192/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             128309               128309               processes
Max open files            4096                 4096                 files
Max locked memory         65536                65536                bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       128309               128309               signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us

Apparently both the soft and the hard limit has been set to the value configured in the service override, but that's not the end of the world.
Both soft and hard limits can be specified with LimitNOFILE=4096:35536.

Updated by offbyone 5 months ago · 3 revisions