以编程方式在 OS X/MacOS 上设置 maxfile

Setting maxfile on OS X/MacOS Programmatically

如果我使用 launchctllimit 命令查看 maxfiles 选项(在我的 OS X El Cap 机器上)

$ launchctl limit
    cpu         unlimited      unlimited      
    filesize    unlimited      unlimited      
    data        unlimited      unlimited      
    stack       8388608        67104768       
    core        0              unlimited      
    rss         unlimited      unlimited      
    memlock     unlimited      unlimited      
    maxproc     709            1064           
    maxfiles    256            unlimited

似乎有 256 的软限制和 "unlimited" 的硬限制。我想将软限制更改为 2048 之类的内容,并保持硬限制不变。当我查看 limit 的参数时

$ launchctl help limit
Usage: launchctl limit [<limit-name> [<both-limits> | <soft-limit> <hard-limit>]

看来我可以将两个限制设置为同一事物,为软和硬设置一个值。但是,如果我尝试设置无限的硬限制。

$ sudo launchctl limit maxfiles 2048 unlimited

我最终得到了奇怪的值 10240

$ launchctl limit
    cpu         unlimited      unlimited      
    filesize    unlimited      unlimited      
    data        unlimited      unlimited      
    stack       8388608        67104768       
    core        0              unlimited      
    rss         unlimited      unlimited      
    memlock     unlimited      unlimited      
    maxproc     709            1064           
    maxfiles    2048           10240          

这是怎么回事?是否可以设置无限值?如果不是,那是 launchctl limit 命令的限制,还是系统级别的限制?如果是后者,unlimited 报告的初始值是多少?或者这个苹果就是苹果?

对于奖励积分 -- 有人知道为什么这个限制首先设置得这么低吗?

Apple 在 Yosemite 中更改了这些内容,但没有推测原因。通过 launchctl limit ... 所做的任何更改仅对您当前的登录名是临时的。重新登录或重启,它们会立即返回到 Apple 设置的默认值。

我可以确认他们从 10.12.4 b4 开始还没有改变这个行为。

当 Apple 就是 Apple 时,这是一种无法令人满意的消化。我深入研究了开发人员文档,但找不到他们进行更改的原因的解释。

来自 man page for setrlimit()launchd 实现此功能所依赖的底层系统调用:

setrlimit() now returns with errno set to EINVAL in places that historically succeeded. It no longer accepts "rlim_cur = RLIM_INFINITY" for RLIM_NOFILE. Use "rlim_cur = min(OPEN_MAX, rlim_max)".

因此,虽然 getrlimit() 可能(最初)报告硬限制是 RLIM_INFINITY,但实际上是 OPEN_MAX (10240),因为这只是由如何施加的限制内核已实现。如果您尝试设置限制,则需要使用后一个值,这会影响从那时起报告的内容。

至于为什么RLIM_NOFILE的软限制默认为256,是因为对于绝大多数进程来说,这不是一个实际的限制。他们在没有接近这个限制的情况下相处得很好。保持值 "so low" 意味着每个进程在内存方面的成本较低,并且每个 fork() 在将文件描述符复制到新子进程等方面的工作较少

知道自己可能会处理更多文件的程序可以使用 setrlimit() 更改自己的限制。