尽管我尽了最大努力,但我还是无法增加每个进程的最大打开文件数。
以下是我所做的:
/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 用户会话之间丢失。