In Linux server administration, file descriptors (FDs) are crucial for applications that handle numerous concurrent connections like databases (HBase, MongoDB), web servers (Nginx, Apache), and big data platforms (Hadoop). The system imposes two types of limits:
- Kernel-level limit (fs.file-max): Global maximum FDs system-wide
- User-level limit (ulimit): Per-process and per-user FD constraints
The Linux security model implements a dual-limit system:
# View current limits
ulimit -Sn # shows soft limit
ulimit -Hn # shows hard limit
Soft Limit: The effective limit enforced during normal operation. Users can self-adjust up to the hard limit.
Hard Limit: The absolute ceiling that requires root privileges to modify.
For modern Linux distributions (Ubuntu 20.04+, CentOS 7+, RHEL 8+):
1. Kernel-Level Configuration
# Check current global limit
cat /proc/sys/fs/file-max
# Permanent setting (persists across reboots)
echo "fs.file-max = 500000" >> /etc/sysctl.conf
sysctl -p
2. User-Level Configuration
Create a dedicated limits configuration file:
# /etc/security/limits.d/90-nproc.conf
* soft nofile 100000
* hard nofile 200000
root soft nofile 200000
root hard nofile 400000
For services started via systemd (common on modern distros):
# Example: Override for MySQL service
sudo mkdir -p /etc/systemd/system/mysql.service.d/
echo '[Service]
LimitNOFILE=200000' | sudo tee /etc/systemd/system/mysql.service.d/limits.conf
systemctl daemon-reload
- Changes not applying? Check if pam_limits is loaded in /etc/pam.d/system-auth
- Systemd services ignoring limits? Use 'LimitNOFILE' in service unit files
- Running into "Too many open files"? Verify with:
lsof -u username | wc -l cat /proc/<pid>/limits
For infrastructure-as-code setups:
#!/bin/bash
# Set kernel FD limit
echo "fs.file-max = 650000" > /etc/sysctl.d/99-file-max.conf
# Configure user limits
cat > /etc/security/limits.d/99-application.conf <
When running server applications like HBase, Hadoop, or high-traffic web servers, properly configuring file descriptor limits is crucial. Linux implements two layers of control:
- Kernel-level limit (fs.file-max): The absolute maximum file descriptors system-wide
- User-level limit (ulimit): Per-process and per-user restrictions
In Linux user sessions:
soft limit - The current enforced value (can be increased up to hard limit)
hard limit - The maximum allowed value (requires root privileges to exceed)
To check current kernel limit:
cat /proc/sys/fs/file-max
For persistent configuration on modern Linux distributions (Ubuntu/CentOS/RHEL):
# Create or modify sysctl configuration
echo 'fs.file-max = 65000' > /etc/sysctl.d/60-file-max.conf
# Apply changes immediately
sysctl -p /etc/sysctl.d/60-file-max.conf
For per-user limits, edit /etc/security/limits.conf
or create files in /etc/security/limits.d/
:
* soft nofile 65000
* hard nofile 65000
root soft nofile 65000
root hard nofile 65000
For immediate application in current session:
ulimit -n 65000 # Temporary setting (soft limit)
ulimit -Hn 65000 # Hard limit (requires privileges)
Check currently applied limits:
# System-wide
cat /proc/sys/fs/file-nr
# Per-process
cat /proc/<pid>/limits | grep 'Max open files'
# Current shell
ulimit -n
For database servers and high-performance applications:
- Calculate required FD count: (active connections × 1.5) + system FDs
- Monitor usage:
watch -n 1 'cat /proc/sys/fs/file-nr'
- For systemd services: Set
LimitNOFILE
in unit files
For infrastructure-as-code setups (Ansible/Puppet/Chef):
# Ansible playbook snippet
- name: Configure file descriptors
hosts: all
tasks:
- name: Set kernel file-max
sysctl:
name: fs.file-max
value: "65000"
state: present
reload: yes
- name: Configure user limits
copy:
dest: /etc/security/limits.d/99-nofile.conf
content: |
* soft nofile 65000
* hard nofile 65000
root soft nofile 65000
root hard nofile 65000
Remember to reboot or have users re-login after changing limits configuration.