没想到一个 open files limit 都能让我有这么多惊喜.
ulimit
和rlimit
是一个东西, 有些文章说ulimit
代表的是user limit
, 限制的是一个 effective user 的总资源, 而rlimit
限制的是一个进程的资源, 这是错的.strace -fT ulimit -n
是不行的, 因为 ulimit 是 shell builtins, 所以strace ulimit
直接报错说找不到命令; 同理which ulimit
也没有输出(我第一次知道 builtins 是不能which
的)man 3 ulimit
说This routine is obsolete. Use getrlimit(2), setrlimit(2), and sysconf(3) instead
, 有理由相信 ulimit 就是 rlimit- 直接看 bash 源码, 在
builtins/ulimit.def
里可以清楚看到 ulimit 就是调用 rlimit, 第一个问题解决了, 以下讨论 rlimit. - rlimit 是限制用户 / 会话 / 进程组的吗? 只有
RLIMIT_NPROC
,RLIMIT_MSGQUEUE
,RLIMIT_SIGPENDING
是按照 real user ID 限制的多个进程的, 分别限制的是进程数, POSIX 消息队列字节数, 排队信号数, 其他都是限制单进程. /proc/$PID/limit
和ulimit
的关系是对应的, 但是如果你在 shell 里ulimit -a
看到的东西和一个进程的/proc/$PID/limit
是不一样的, 不要慌, rlimit 是继承的, 所以看看父进程, 看看不同用户的 rlimit 是否不一样, 看看进程自己是否修改了.docker run --ulimit
是在 docker 层做的! 我意思是, 这不是交给 containerd 和 runc 做的, runc 对此一无所知. 不过具体在哪一步设置的我还不清楚, 我的 docker 解剖计划已经拖延很久了.- 进程出现了
accept4: too many open files in system
之类的日志, 但是lsof -p
或者/proc/$PID/fd/
数出来的 fd 都明显没有超过 rlimit, 那么可以考虑全局 fd 限制. cat /proc/sys/fs/file-max
定义了the maximum number of file-handles that the Linux kernel will allocate
, 而超过这个限制的话可以在内核日志里看到VFS: file-max limit <number> reached
.- 查看一个进程使用的 open files number, 如果想通过 syscall 的话, 只有一个
getrusage(2)
可以用, 不过只能查看自己或者子进程的 rlimit usage, 所以如果我作为 sibling 也是无法查看的... - 回到上面说的全局内核 file-handles,
cat /proc/sys/fs/file-nr
记录了the number of allocated file handles, the number of allocated but unused file handles, and the maximum number of file handles
, 不过我自己试了一下, 第一个数不是即时修改的, 所以参考价值不大.