如何在 golang 中执行套接字激活,将套接字作为 stdin/out 传递给子进程?
How to perform socket activation, passing a socket to a child proc as stdin/out, in golang?
我有一个 运行 通过 systemd 套接字激活的 C 程序。 Systemd 监听一个端口,当一个 TCP 连接进入时,应用程序启动,它对待 stdin/stdout 完全像 套接字(IE:setsockopt 等)。
我正在尝试用一个小的启动程序来模仿这种行为。当连接到它时,它只会被告知要监听哪个端口以及向 运行 发送什么命令(其他高级 systemd 功能的 none)。
我遇到的问题是我似乎无法将连接作为套接字传递给 stdin/out。将 TCPConn 传递给 Stdin
和 Cmd
的 Stdout
没有工作(C 程序在 setsockopts 上出错)。
cmd := exec.Cmd{
Path: cmds,
Args: args,
Stdin: conn.,
Stdout: conn,
Stderr: os.Stderr,
}
err = cmd.Run()
我看到 article 关于如何使用 dup(2)
和 fork 在 C 中做这样的事情,但是
- 它正在分叉而不是执行另一个子进程
- 我不完全理解套接字 fd 被复制而不是
client
接受的连接
有没有办法在 Golang 中做这样的事情?
附加信息
套接字文件看起来大致像
[Unit]
Description=soc activated program
[Socket]
ListenStream=0.0.0.0:10101
Accept=yes
[Install]
WantedBy=sockets.target
相应的单元文件如下所示:
[Unit]
Description=My Program
[Service]
Type=simple
ExecStart=/usr/bin/myprog -N
StandardInput=socket
StandardOutput=socket
StandardError=journal
TimeoutStopSec=5
KillMode=process
[Install]
WantedBy=multi-user.target
使用连接的 file:
f, err := conn.File()
if err != nil { /* TODO handle error */}
defer f.Close()
cmd := exec.Cmd{
Path: cmds,
Args: args,
Stdin: f,
Stdout: f,
Stderr: os.Stderr,
}
err = cmd.Run()
我有一个 运行 通过 systemd 套接字激活的 C 程序。 Systemd 监听一个端口,当一个 TCP 连接进入时,应用程序启动,它对待 stdin/stdout 完全像 套接字(IE:setsockopt 等)。
我正在尝试用一个小的启动程序来模仿这种行为。当连接到它时,它只会被告知要监听哪个端口以及向 运行 发送什么命令(其他高级 systemd 功能的 none)。
我遇到的问题是我似乎无法将连接作为套接字传递给 stdin/out。将 TCPConn 传递给 Stdin
和 Cmd
的 Stdout
没有工作(C 程序在 setsockopts 上出错)。
cmd := exec.Cmd{
Path: cmds,
Args: args,
Stdin: conn.,
Stdout: conn,
Stderr: os.Stderr,
}
err = cmd.Run()
我看到 article 关于如何使用 dup(2)
和 fork 在 C 中做这样的事情,但是
- 它正在分叉而不是执行另一个子进程
- 我不完全理解套接字 fd 被复制而不是
client
接受的连接
有没有办法在 Golang 中做这样的事情?
附加信息
套接字文件看起来大致像
[Unit]
Description=soc activated program
[Socket]
ListenStream=0.0.0.0:10101
Accept=yes
[Install]
WantedBy=sockets.target
相应的单元文件如下所示:
[Unit]
Description=My Program
[Service]
Type=simple
ExecStart=/usr/bin/myprog -N
StandardInput=socket
StandardOutput=socket
StandardError=journal
TimeoutStopSec=5
KillMode=process
[Install]
WantedBy=multi-user.target
使用连接的 file:
f, err := conn.File()
if err != nil { /* TODO handle error */}
defer f.Close()
cmd := exec.Cmd{
Path: cmds,
Args: args,
Stdin: f,
Stdout: f,
Stderr: os.Stderr,
}
err = cmd.Run()