首页 > 解决方案 > 捕获标准输出时文件描述符过多

问题描述

我的 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 机器中绕过这个限制?

标签: linuxmacosgofile-descriptor

解决方案


没有足够的文件描述符通常是由文件描述符泄漏引起的。例如,在不再需要打开的文件或网络套接字后忘记调用 .Close。

如果您想同时打开超过 1024 个文件/网络连接,请有意。ulimit您可以使用命令(和适当的标志)增加此限制。此命令将增加当前 shell 会话的限制,如果涉及单元测试,这似乎是合适的。


推荐阅读