UDP 守护进程的 systemd-activate 套接字激活
systemd-activate socket activation for UDP daemons
我喜欢在开发过程中使用 systemd-activate(8)
来 测试 套接字激活的守护进程,
然而,它似乎只监听 TCP 连接:
% /usr/lib/systemd/systemd-activate -l 5700 ./prog
Listening on [::]:5700 as 3.
% netstat -nl |grep 5700
tcp6 0 0 :::5700 :::* LISTEN
我正在使用处理数据报 (UDP) 的程序。如何让 systemd-activate
监听 UDP 端口?或者有没有
使用其他工具执行此操作的简单方法,无需费心制作和安装 systemd 单元文件?
我不确定 systemd-activate
是否有办法做到这一点。
您可能想要使用一些 .service
单元文件和一个 .socket
具有依赖关系的单元文件。在 .socket
单元中,您将描述 ListenDatagram=
选项。有关详细信息,请参阅 here。
我最终编写了一个简单的 C 程序来完成这项工作;下面的代码(public 域)。
用法是:
./a.out <port-number> <prog> [<arg1> ...]
该程序在 <port-number>
上打开一个 UDP 套接字,设置 systemd 套接字激活的守护进程期望的环境变量,然后使用后面的任何参数执行 <prog>
。
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
int main(int argc, char **argv) {
if (argc < 2) {
printf("no port specified\n");
return -1;
}
if (argc < 3) {
printf("no program specified\n");
return -1;
}
uint16_t port = htons((uint16_t) strtoul(argv[1], NULL, 10));
if (port == 0 || errno) {
printf("failed to parse port: %s\n", argv[1]);
return -1;
}
/* create datagram socket */
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
printf("failed to open socket; errno: %d\n", errno);
return -1;
}
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = port;
sa.sin_addr.s_addr = INADDR_ANY;
/* bind socket to port */
int r = bind(fd, (struct sockaddr *) &sa, sizeof(struct sockaddr_in));
if (r < 0) {
printf("bind failed; errno: %d\n", errno);
return -1;
}
/* execute subprocess */
setenv("LISTEN_FDS", "1", 0);
execvp(argv[2], argv + 2);
}
这是最近添加到 systemd-activate
:https://github.com/systemd/systemd/pull/2411,并且在发布时将成为 systemd-229 的一部分。
我喜欢在开发过程中使用 systemd-activate(8)
来 测试 套接字激活的守护进程,
然而,它似乎只监听 TCP 连接:
% /usr/lib/systemd/systemd-activate -l 5700 ./prog
Listening on [::]:5700 as 3.
% netstat -nl |grep 5700
tcp6 0 0 :::5700 :::* LISTEN
我正在使用处理数据报 (UDP) 的程序。如何让 systemd-activate
监听 UDP 端口?或者有没有
使用其他工具执行此操作的简单方法,无需费心制作和安装 systemd 单元文件?
我不确定 systemd-activate
是否有办法做到这一点。
您可能想要使用一些 .service
单元文件和一个 .socket
具有依赖关系的单元文件。在 .socket
单元中,您将描述 ListenDatagram=
选项。有关详细信息,请参阅 here。
我最终编写了一个简单的 C 程序来完成这项工作;下面的代码(public 域)。
用法是:
./a.out <port-number> <prog> [<arg1> ...]
该程序在 <port-number>
上打开一个 UDP 套接字,设置 systemd 套接字激活的守护进程期望的环境变量,然后使用后面的任何参数执行 <prog>
。
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
int main(int argc, char **argv) {
if (argc < 2) {
printf("no port specified\n");
return -1;
}
if (argc < 3) {
printf("no program specified\n");
return -1;
}
uint16_t port = htons((uint16_t) strtoul(argv[1], NULL, 10));
if (port == 0 || errno) {
printf("failed to parse port: %s\n", argv[1]);
return -1;
}
/* create datagram socket */
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
printf("failed to open socket; errno: %d\n", errno);
return -1;
}
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = port;
sa.sin_addr.s_addr = INADDR_ANY;
/* bind socket to port */
int r = bind(fd, (struct sockaddr *) &sa, sizeof(struct sockaddr_in));
if (r < 0) {
printf("bind failed; errno: %d\n", errno);
return -1;
}
/* execute subprocess */
setenv("LISTEN_FDS", "1", 0);
execvp(argv[2], argv + 2);
}
这是最近添加到 systemd-activate
:https://github.com/systemd/systemd/pull/2411,并且在发布时将成为 systemd-229 的一部分。