How to set a global nofile limit to avoid "many open files" error?

Learn how to set a global nofile limit to avoid "many open files" error? with practical examples, diagrams, and best practices. Covers linux, ubuntu, linux-kernel development techniques with visual...

Setting a Global 'nofile' Limit to Prevent 'Too Many Open Files' Errors

Hero image for How to set a global nofile limit to avoid "many open files" error?

Learn how to configure system-wide and user-specific 'nofile' limits on Linux to prevent applications from encountering 'Too many open files' errors, ensuring system stability and performance.

The "Too many open files" error, often seen as EMFILE or ulimit: open files: cannot modify limit: Operation not permitted, is a common issue in Linux environments, especially for applications that handle a large number of connections or files. This error indicates that a process has exceeded its allowed number of open file descriptors. While individual processes can have their limits adjusted, a more robust solution often involves setting global or system-wide nofile limits. This article will guide you through understanding, configuring, and verifying these limits on Linux systems, with a focus on Ubuntu and Upstart-managed services.

Understanding File Descriptors and 'nofile' Limits

In Unix-like operating systems, everything is treated as a file, including network sockets, pipes, and actual disk files. When a program interacts with any of these, it uses a file descriptor (FD). Each process has a limit on the number of FDs it can open simultaneously. This limit is controlled by the nofile parameter, which can be set at various levels: per-process, per-user, and system-wide. Exceeding this limit can lead to application crashes, service interruptions, and general system instability.

flowchart TD
    A[Application Starts] --> B{Needs File Descriptor}
    B --> C{Check Process 'nofile' Limit}
    C -->|Limit Exceeded| D[Error: "Too Many Open Files"]
    C -->|Limit OK| E[Open File Descriptor]
    E --> F{Continue Operations}
    F --> B
    D --> G[Application Crash/Failure]
    subgraph System Limits
        H[System-wide 'nofile' Limit]
        I[User-specific 'nofile' Limit]
    end
    H --- C
    I --- C

Flowchart illustrating how file descriptor limits affect an application.

Configuring System-Wide 'nofile' Limits

The primary way to set system-wide nofile limits is by modifying the /etc/sysctl.conf file. This file contains kernel parameters that are applied at boot time. The relevant parameter is fs.file-max, which defines the maximum number of file handles the kernel can allocate. Additionally, you can set default limits for all users and processes via /etc/security/limits.conf.

# Edit /etc/sysctl.conf
sudo nano /etc/sysctl.conf

# Add or modify the following line:
fs.file-max = 200000

# Apply the changes immediately
sudo sysctl -p

Setting the system-wide maximum number of file handles.

# Edit /etc/security/limits.conf
sudo nano /etc/security/limits.conf

# Add these lines at the end of the file to set default limits for all users
# * represents all users
# soft is the current limit, hard is the maximum limit a user can set for themselves
*    soft    nofile    65536
*    hard    nofile    65536

# For a specific user (e.g., 'myuser')
# myuser    soft    nofile    65536
# myuser    hard    nofile    65536

Setting default 'nofile' limits for all users via limits.conf.

Handling Upstart Services (Ubuntu 14.04 and older)

For systems using Upstart (common in Ubuntu 14.04 and older), setting nofile limits requires a different approach for services. Upstart scripts often run before limits.conf is fully applied to the service's environment. You can directly specify the limit nofile directive within the Upstart service configuration file.

# Example Upstart service file: /etc/init/my-service.conf

description "My Awesome Service"

start on runlevel [2345]
stop on runlevel [!2345]

# Set the nofile limit for this specific service
limit nofile 65536 65536

exec /usr/local/bin/my-service-executable

# Restart the service after modifying the file
sudo service my-service restart

Setting 'nofile' limits directly in an Upstart service configuration file.

Verifying 'nofile' Limits

After making changes, it's crucial to verify that the new limits have been applied correctly. You can check the system-wide maximum, the current user's limits, and the limits of a running process.

1. Check System-Wide Maximum

To see the kernel's maximum allowed file handles, use the sysctl command:

2. Check Current User's Limits

To view the nofile limits for your current shell session, use the ulimit command:

3. Check a Specific Process's Limits

To check the limits of a running process, you need its Process ID (PID). First, find the PID (e.g., using pgrep or ps aux), then inspect its /proc/<PID>/limits file:

sysctl fs.file-max

Command to check the system-wide maximum file handles.

ulimit -n

Command to check the current user's 'nofile' limit.

# Find the PID of your process (replace 'my-service' with your actual service name)
PID=$(pgrep my-service)

# Check the limits for that PID
cat /proc/$PID/limits

Commands to check the 'nofile' limits for a specific running process.