如何安全地将net.Listener()的FD传递给子进程?

7

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

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

我通过许多开源代码进行了研究,也进行了一些实验。但不幸的是,目前没有一个解决方案能够满足我的需求,因为它们不可移植,还需要许多危险的低级工作。

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

我现在尝试过的方法:

  1. 环境变量值不可移植,会对许多FDs造成混乱,不安全,因为可以从外部更改。

  2. Dup FD&清除FD_CLOEXEC然后执行/ fork,可移植但不受Go API支持,已提交syscall.NoCloseOnExec()更改给开发团队,但被拒绝,因为他们想保持syscall的干净。

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

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

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

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

同时在OS X和Linux上包含2个可执行文件。我尝试过Go 1.1和Go 1.1.1,但这个问题仍然存在。


你介意贴一些代码吗?特别是那些你想避免的不安全的部分?这将有助于回答你的问题。 - tike
我将稍后发布我的解决方案,但现在不会,因为这可能会设置限制。 - Shane Hou
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。


我认为 []*os.File{l} 应该改为 []*os.File{f}。使用环境变量并不是一个好主意,因为可能会有多个 FDs 在运行。我稍后会测试这个解决方案。 - Shane Hou
另一个问题是如何从子进程获取继承的文件描述符?你没有展示3,“listener”是怎么来的。实际上,这部分对于可扩展的服务非常重要。此解决方案也存在一个错误:http://golang.org/pkg/os/exec/#Cmd,请查看“ExtraFiles []*os.File”上面的评论。 - Shane Hou
我已经测试了这段代码,发现它在OS X和CentOS上都无法工作。很抱歉,但目前似乎只有清晰的FD_CLOEXEC可以使用。 - Shane Hou

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()


1
我在golang.org上看到TCPListen和TCConn没有实现,有什么在Windows上的建议吗?https://golang.org/src/net/tcpsock.go?s=227:332#L5 - Phane Janee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接