无法在 22.04 中增加每个进程的最大打开文件数

无法在 22.04 中增加每个进程的最大打开文件数

尽管我尽了最大努力,但我还是无法增加每个进程的最大打开文件数。

以下是我所做的:

/etc/systemd/用户.conf

DefaultLimitNOFILE=20000500

/etc/systemd/system.conf

DefaultLimitNOFILE=20000500

/etc/security/limits.conf

* soft nofile 20000500
* hard nofile 20000500

/etc/pam.d/common-session

...
session required        pam_limits.so

/etc/pam.d/common-session-noninteractive

...
session required        pam_limits.so

/etc/sysctl.conf

fs.inotify.max_user_watches=52428800
fs.file-max=25000500
fs.nr_open=20000500

完成所有这些后,我有一个用于测试的 Python 脚本。此脚本的目的是尝试打开1048577文件并查看是否失败,因为我的ulimit -Hn报告值为1048576

import os

def test_open_file_descriptors(num_files):
    fds = []
    try:
        for i in range(num_files):
            fd = os.open("/etc/passwd", os.O_RDONLY)
            fds.append(fd)
            if i % 1000 == 0:
                print(f"Opened {i} files")
    except Exception as e:
        print(f"Error encountered. Failed to open i={i}: {e}")
    finally:
        for fd in fds:
            os.close(fd)

if __name__ == "__main__":
    num_files = 1048577  # 1,048,577 files
    test_open_file_descriptors(num_files)

无论我做什么,程序在打印出它能够打开 1048000 个文件后就会失败。

...
Opened 1047000 files
Opened 1048000 files
Error encountered. Failed to open i=1048573: [Errno 24] Too many open files: '/etc/passwd'

我遗漏了什么?为什么我似乎无法打开超过 1048576 个文件?要怎么做才能将此限制增加到 10,000,000 个?

答案1

第1部分:回答问题(在问题被编辑之前)关于当限制为 1048576 时仅获取 1048573 个文件?:

尽管ulimit -Hn可能会说1048576,但还会有几个开销文件句柄与该过程相关。

为了这个例子,为了让我有时间去研究,我在关闭文件并退出之前在你的程序中插入了一个睡眠:

...
finally:
    time.sleep(int(300))
    for fd in fds:
        ...

我和你得到同样的结果:

...
Opened 1047000 files
Opened 1048000 files
Error encountered. Failed to open i=1048573: [Errno 24] Too many open files: '/etc/passwd'

但是它们是开销文件句柄等等:

doug@s19:~$ ls -l /proc/1449/fd | grep passwd | wc -l
1048573
doug@s19:~$ ls -l /proc/1449/fd | grep -v passwd | wc -l
4
doug@s19:~$ ls -l /proc/1449/fd | grep total | wc -l
1
doug@s19:~$ ls -l /proc/1449/fd | head
total 0
lrwx------ 1 doug doug 64 Apr 19 16:27 0 -> /dev/pts/0
lrwx------ 1 doug doug 64 Apr 19 16:27 1 -> /dev/pts/0
lr-x------ 1 doug doug 64 Apr 19 16:27 10 -> /etc/passwd
lr-x------ 1 doug doug 64 Apr 19 16:27 100 -> /etc/passwd
lr-x------ 1 doug doug 64 Apr 19 16:27 1000 -> /etc/passwd
lr-x------ 1 doug doug 64 Apr 19 16:27 10000 -> /etc/passwd
lr-x------ 1 doug doug 64 Apr 19 16:27 100000 -> /etc/passwd
lr-x------ 1 doug doug 64 Apr 19 16:27 1000000 -> /etc/passwd
lr-x------ 1 doug doug 64 Apr 19 16:27 1000001 -> /etc/passwd
doug@s19:~$ cat /proc/sys/fs/nr_open
1048576
doug@s19:~$ ulimit -Sn
1048576
doug@s19:~$ ulimit -Hn
1048576
... EDIT: added later, hence different PID ...
doug@s19:~$ ls -l /proc/1649/fd | grep -v total | grep -v passwd
lrwx------ 1 doug doug 64 Apr 19 17:30 0 -> /dev/pts/0
lrwx------ 1 doug doug 64 Apr 19 17:30 1 -> /dev/pts/0
lrwx------ 1 doug doug 64 Apr 19 17:30 2 -> /dev/pts/0

我无法将 ulimits 设置为高于 1048576,但我可以写入更大的数字/proc/sys/fs/nr_open

第2部分:回答问题:What does one have to do to increase this limit to, say, 10,000,000?

默认内核编译时打开文件限制定义为,fs/file.c:unsigned int sysctl_nr_open __read_mostly = 1024*1024;并且启动时间限制将限制在该限制内,正如您所发现的。因此,对于普通用户来说,这个问题的简短答案是您不能。

对于 root 用户来说,较长的答案是更改启动后值:

root@s19:/media/nvme/home/doug/csv-plot/tmp# echo 16777216 > /proc/sys/fs/nr_open
root@s19:/media/nvme/home/doug/csv-plot/tmp# ulimit -H -n 16777216
root@s19:/media/nvme/home/doug/csv-plot/tmp# ulimit -S -n 16777216

完成后,我将您的程序更改为要求打开 1500 万个文件并从相同的根会话运行它:

...
Opened 14994000 files
Opened 14995000 files
Opened 14996000 files
Opened 14997000 files
Opened 14998000 files
Opened 14999000 files

作为普通用户,我无法执行此操作,并且 ulimit 设置也会在 root 用户会话之间丢失。

相关内容