我有一个中等规模的 Raku 项目,突然在启动时抛出以下错误:
===SORRY!=== Error while compiling /home/patrickb/repos/RakudoCIBot/service.raku
===SORRY!=== Error while compiling /home/patrickb/repos/RakudoCIBot/lib/RakudoCIBot.rakumod (RakudoCIBot)
Now hiting the error and sleeping
===SORRY!=== Error while compiling /home/patrickb/repos/RakudoCIBot/lib/Routes.rakumod (Routes)
Earlier failure:
Failed to open file /home/patrickb/.raku/precomp/F494CC98E40B399BDACD0E2436C176FDE8706DE8/28/287E340591A8C5DE2625947EEC5BEFDF29E8EA4F: Too many open files
in any statement_control at /home/patrickb/rrepos/install/share/perl6/lib/Perl6/Grammar.moarvm line 1
Final error:
Type check failed in binding; expected IO::Handle but got Failure (Failure.new(exceptio...)
at /home/patrickb/repos/RakudoCIBot/lib/Routes.rakumod (Routes):10
at /home/patrickb/repos/RakudoCIBot/lib/RakudoCIBot.rakumod (RakudoCIBot):15
at /home/patrickb/repos/RakudoCIBot/service.raku:3
删除
/home/patrickb/repos/RakudoCIBot/.precomp/
文件夹使其再次成功启动一次。但这既不是解决方案,也不是可接受的解决方法。
发生了什么事,我能做什么来解决这个问题?
#raku IRC 频道中的人们对解决这个问题非常有帮助。
在出现错误的地方停止进程(我编译了自己的 Rakudo 并在打印错误消息之前放置了
sleep
。)并查看其中一个 rakudo 编译器进程的 /proc/$PID/fd
显示它正好有 1024文件打开 (ls -1 /proc/$PID/fd | wc -l
)。大多数文件如下所示:
lr-x------. 1 patrickb patrickb 64 Jun 13 17:20 965 -> /home/patrickb/.raku/precomp/F494CC98E40B399BDACD0E2436C176FDE8706DE8/EA/EA68508E655FD3F22D1AE0A8666B86469073473
所以是编译器打开了很多预编译文件。这实际上是非常合理的,因为依赖关系树可以轻松地在具有一两个较大依赖关系的重要项目中包含超过 1000 个文件。 (就我而言,部门中有 Red 和 Cro。)
ulimit -Sn
打印 1024
。所以我设定了一个相当低的限制。在运行我的应用程序之前调用 ulimit -n 4096
使其可以工作。
考虑到上述所有内容,干净的解决方案似乎是将以下内容添加到
/etc/security/limits.conf
:
# Increase nofile soft from the default of 1024.
# The Rakudo compiler sometimes hits the limit.
* soft nofile 4096