7

我已经被这个问题困扰了几个小时:

我有一个主进程作为 TCP 服务器,主进程调用 Fork(),将其 net.Listener() 的 FD 传递给子进程。然后子进程可以使用 net.Filelistener() 来继承这个 FD。

我通过许多开源代码研究了这个问题,也做了一些实验。但不幸的是,这些解决方案目前都不能让我满意,因为它们不可移植,你还需要许多危险的低级工作。

如果有任何解决方案可以安全地将 net.Listener() 的 FD 传递给子进程,我很高兴知道。

我现在尝试过的:

  1. 环境值,不可移植,会导致许多 FD 混乱,不安全,因为可以从外部更改。

  2. Dup FD & ClearFD_CLOEXEC然后 exec/fork,可移植但不受 Go API 支持,syscall.NoCloseOnExec()提交给开发团队的更改被拒绝,因为他们希望保持系统调用干净。

  3. 设置SO_REUSEADDR子进程可以立即监听端口,在此之前关闭父进程的监听器。失败,不可移植,Go API 不支持,也不安全。

  4. exec.Command.ExtraFiles(),不知道如何从子进程获取继承的 FD,我需要一个配置文件来保存 FD 和名称吗?此解决方案也有一个错误,请阅读 exec 的文档以获取更多详细信息。

好的,我已经为这个问题编写了一个简单的测试用例(带有解决方案 4):

https://github.com/reckhou/go-fd-pass-test

还包括 2 个 OS X 和 Linux 上的可执行文件。我试过 Go 1.1 & Go 1.1.1 但这个问题仍然存在。

4

2 回答 2

5

最简单的方法是在 exec.Cmd 的 ExtraFiles 字段中传递侦听器。

父母的例子:

var l *net.TCPListener
cmd := exec.Command(...)
f, err := l.File()
cmd.ExtraFiles = []*os.File{f}

孩子的例子:

l, err := net.FileListener(os.NewFile(3, "listener"))

您可能还想概括这一点并让孩子接受 PROGRAMNAME_LISTENER_FD 作为环境变量。然后父母会在启动孩子之前将环境变量设置为3。

于 2013-06-19T18:00:37.323 回答
1

我正在寻找相同的监听环回地址并读取数据并发送到 WINDOWS 中的 exec 命令。

任何关于 Windows 的建议都不支持 UNIX 中的文件描述符 我们按照以下方式进行操作

service := ":1200" tcpAddr, err := net.ResolveTCPAddr("tcp", service)

listener, err := net.ListenTCP("tcp",tcpAddr)
if err != nil {
    return "", err
}

defer listener.Close()
file, err := listener.File()   --> unix supports file descriptor / how about in windows ??
if err != nil {  
    return "", err
}

cmd := exec.Command( execname)

cmd.ExtraFiles = []*os.File{file} --> 在 unix 中它支持 / 在 windows 中添加数据怎么样???

cmd.Start()

于 2018-12-08T23:18:26.710 回答