When I recently inspected our Redis instance's file descriptor limits via cat /proc/<redis-pid>/limits
, the output showed a puzzling 4016 limit despite our system-wide configurations:
# Current process limits
Limit Soft Limit Hard Limit
Max open files 4016 4016
We had properly configured multiple levels of settings:
# /etc/security/limits.conf
* soft nofile 100000
* hard nofile 100000
# /etc/sysctl.conf
fs.file-max = 100000
# /etc/pam.d/sshd
session required pam_limits.so
On Debian systems using systemd (which includes Squeeze and later), services often ignore traditional PAM limits. Redis installed via package manager typically uses systemd for process management. Here's how to verify:
systemctl status redis-server
For systemd-managed services, we need to set limits in the service unit file. Create or modify:
# /etc/systemd/system/redis-server.service.d/limits.conf
[Service]
LimitNOFILE=100000
Then reload and restart:
systemctl daemon-reload
systemctl restart redis-server
After making changes, verify with:
# Check systemd's view
systemctl show redis-server --property LimitNOFILE
# Check actual process
cat /proc/$(pgrep redis-server)/limits | grep "Max open files"
For older systems not using systemd, edit the init script:
# /etc/init.d/redis-server
ulimit -n 100000
# Add this before the actual startup command
- Always restart the service after changes
- Check for duplicate configuration files
- Remember that systemd has separate soft and hard limit settings
- System-wide limits in limits.conf
- Kernel parameters in sysctl.conf
- Systemd service overrides (if applicable)
- PAM configuration for SSH sessions
When examining our Redis server's process limits via cat /proc/<redis-pid>/limits
, we encountered a puzzling scenario:
Limit Soft Limit Hard Limit
Max open files 4016 4016
This persisted despite having proper configurations in:
/etc/sysctl.conf
:fs.file-max = 100000
/etc/security/limits.conf
:* soft nofile 100000
- PAM configuration files
Linux process limits follow strict inheritance rules. The key factors affecting our Redis process:
# Verify system-wide file descriptors
cat /proc/sys/fs/file-max
# Check current user limits (run as redis user)
ulimit -n
Common reasons for limit propagation failures:
- Systemd service files overriding limits
- Init script spawning processes before PAM applies limits
- Containerization breaking traditional limit inheritance
On Debian systems using systemd (since Jessie), Redis typically installs with:
# /lib/systemd/system/redis-server.service
[Service]
Type=forking
User=redis
Group=redis
# Often missing LimitNOFILE directive
Solution (for systemd systems):
# Create override file
sudo mkdir -p /etc/systemd/system/redis-server.service.d
echo '[Service]
LimitNOFILE=100000' | sudo tee /etc/systemd/system/redis-server.service.d/override.conf
# Reload and restart
sudo systemctl daemon-reload
sudo systemctl restart redis-server
For legacy systems like Debian Squeeze:
# Edit init script (typically /etc/init.d/redis-server)
# Add ulimit call before launching server
ulimit -n 100000
exec /usr/local/bin/redis-server /etc/redis.conf
After making changes:
# Check current process
cat /proc/$(pgrep -u redis redis-server)/limits | grep "Max open files"
# Alternative method using prlimit
sudo apt-get install util-linux
prlimit -p $(pgrep redis-server) --nofile
For comprehensive solutions:
# 1. Set in redis.conf directly
# maxclients 100000
# 2. Combine with pam_limits
# /etc/pam.d/common-session
session required pam_limits.so
# 3. Configure security limits
# /etc/security/limits.d/redis.conf
redis soft nofile 100000
redis hard nofile 100000
Remember that the fs.file-max
sysctl setting controls the system-wide limit, while per-process limits are controlled via ulimit mechanisms.