猿问

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

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

我有一个主进程作为 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

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


长风秋雁
浏览 179回答 2
2回答

撒科打诨

最简单的方法是在 exec.Cmd 的 ExtraFiles 字段中传递侦听器。父母的例子:var l *net.TCPListenercmd := exec.Command(...)f, err := l.File()cmd.ExtraFiles = []*os.File{f}孩子的例子:l, err := net.FileListener(os.NewFile(3, "listener"))您可能还想对此进行概括并让孩子接受 PROGRAMNAME_LISTENER_FD 作为环境变量。然后在启动子进程之前,父进程将环境变量设置为 3。

catspeake

我正在寻找相同的方法来监听环回地址并读取数据并发送到 WINDOWS 中的 exec 命令。任何建议,因为 Windows 不支持 UNIX 中的文件描述符,我们按照以下步骤操作服务:=“:1200”tcpAddr,错误:= net.ResolveTCPAddr(“tcp”,服务)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()
随时随地看视频慕课网APP

相关分类

Go
我要回答