linux - 捕获标准输出时文件描述符过多
问题描述
我的 Go 项目中有数千个测试,为了确保 CLI 的正确输出,我编写了一个函数来捕获标准输出:
// captureStdout captures everything written to the terminal and returns it as a string.
func captureStdout(f func(w io.Writer)) string {
originalStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
f(w)
_ = w.Close()
out, _ := ioutil.ReadAll(r)
os.Stdout = originalStdout
_ = r.Close()
return string(out)
}
// No error handling for smaller code snippet
这个函数工作正常,但是当我运行它几千次时,它随机失败。
我发现,这与 Linux 上的文件描述符限制有关,即 1024。
Linux 系统将任何一个进程可以打开的文件描述符的数量限制为每个进程 1024 个。(这种情况在 Solaris 机器、x86、x64 或 SPARC 上不是问题)。在目录服务器超过每个进程 1024 的文件描述符限制后,任何新进程和工作线程都将被阻止。-来源
在 Windows 上,测试完美无缺。
我将如何在 Go for Linux 机器中绕过这个限制?
解决方案
没有足够的文件描述符通常是由文件描述符泄漏引起的。例如,在不再需要打开的文件或网络套接字后忘记调用 .Close。
如果您想同时打开超过 1024 个文件/网络连接,请有意。ulimit
您可以使用命令(和适当的标志)增加此限制。此命令将增加当前 shell 会话的限制,如果涉及单元测试,这似乎是合适的。