我编写了一个程序,以递归方式读取一个目录中的文件,修改它们并将它们写入另一个目录。每次我运行该程序时,它会在经过几百次迭代后发生错误。我只是再次运行它,它似乎完成了任务。
nodejs或Mac OS X,或者很可能是Mac-OS-X上的nodejs,似乎对可以一次打开的文件数量有某种限制。搜索周围,我发现解决方案是使用类似ulimit -n 10480
的东西,一切都会好的。这是正确的方法吗?本能地,我宁愿不修改我的系统设置,而是修改我的程序以在限制范围内工作。
观察:早些时候我曾经使用Perl来完成我上面描述的任务,我从来没有遇到过任何问题。我假设这是因为我打开,转换,然后关闭文件,然后继续前进。在nodejs中,使用async
模式,我无法在进入下一个文件之前关闭文件。如果我在sync
模式下执行任务,则可以正常工作。
答案 0 :(得分:1)
您可以将async库与limit命令一起使用,以将处理的文件数限制为特定数量。例如:
async.eachLimit(files, 1000, function (file, next) {
processFile(file, next);
}, done);
如果您希望在转到下一个文件之前处理单个文件,只需使用eachSeries。
async.eachSeries(files, function (file, next) {
processFile(file, next);
}, done);
答案 1 :(得分:1)
是的,macOS(可能还有每个UNIX变体)对打开文件的数量有限制,是的,Perl没有你提到的那个问题。
ulimit
不是一个设置你似乎想到它的方式的系统。 ulimit
适用于当前进程,并在启动时复制到其子进程,这意味着如果在进程中提高限制,则不会影响其他进程,如果您是改变某些全局约束资源(如物理内存使用)的限制,可能会使其他程序挨饿。换句话说,如果在shell中运行ulimit -n 10480
,效果只会持续到退出该shell。
在macOS上,系统范围的打开文件的实际上限由命令sysctl kern.maxfiles
给出。无论ulimit
设置如何,如果您尝试一次打开整个系统上的文件,打开文件将失败。在我的系统上,它是12288.这是“系统设置”,修补可以产生更持久的效果:提高它会增加内核所需的静态内存量(按我不知道的数量),降低它可能会使进程从文件描述符。
如果您的脚本相对较短,则使用ulimit
提高文件描述符限制可能不是问题。
虽然我不知道node.js,也许(几乎可以肯定)它一次只能启动一些异步任务,所以你也可以这样做。