从套接字停止服务

从套接字停止服务

我在远程停止服务时遇到问题。

我有一个简单的套接字/服务对:

# /etc/systemd/system/foo.socket
[Unit]
Description=The socket

[Socket]
ListenStream=11111
# /etc/systemd/system/foo.service
[Unit]
Description=The service

[Service]
Type=simple
ExecStart=sleep infinity

之后systemctl start foo.socket看起来像:

foo.socket:  active (listening)
foo.service: inactive (dead)

然后与另一台机器建立连接netcat 10.10.1.16 11111,我们得到:

foo.socket:  active (running)
foo.service: active (running)

完美的!

现在,如果我们终止连接(SIGTERMto netcat),我们会得到:

foo.socket:  active (running)
foo.service: active (running)

但我预计:

foo.socket:  active (listening)
foo.service: inactive (dead)

如何使用TCP连接远程停止服务?

我试过了:

  • Accept=yes[email protected]
  • 提供服务PartOf=foo.socketRequires=foo.socket
  • StandardInput=socket以及标准输出和标准错误。

答案1

而不是/bin/sleep infinity你想运行不同的东西:

[Service]
Type=simple
ExecStart=foo
StandardInput=socket

其中任何一个在哪里foo

#include <stdio.h>
int main(int, char**) {
  char buf[256];
  while(scanf("%255s",buf) > 0) {}
  return 0;
}
#!/bin/sh
while read line; do
  echo "$line"
done < "${1:-/dev/stdin}"
#!/usr/bin/python3
import sys
for line in sys.stdin:
    pass
#!/usr/bin/perl
while (<>) {
  if (eof()) { exit }
}

解释:

当您使用某个Type=simple服务时,该进程一结束,该服务就会停止ExecStart。因此,即使您关闭连接,服务也不会停止,因为应用程序不知道它应该退出。 Systemd 不会发送 SIGTERM,也不需要发送。

相反,我提供了四个ExecStart执行相同操作的进程的实现(C、sh、python、perl):从 stdin 读取,直到 stdin 不再可用。当连接关闭时,流结束,这意味着 stdin 结束。因此,只需继续阅读 stdin 直到得到 EOF,然后退出。一旦您的进程退出,服务就会停止。


内置函数

如果您不想部署上述脚本之一,请使用侦听 stdin 并在 EOF 时退出的内置工具之一。副作用是他们可能真的做了一些事情。我第一个能想到的是grep -EXIT_FAILURE如果它不匹配任何内容,它就会返回,因此在它前面加上前缀-,以确保每次关闭连接时不会导致服务失败。

[Service]
Type=simple
ExecStart=-/bin/grep -
StandardInput=socket

如果您认为利用这个过程可能很有趣,那么也许可以让您的联系做一些有用的事情。我能想到的第二个程序是python3。因此,现在您可以让整个口译员闲置待命,等待为您做点什么。如果您不添加一些沙箱,这可能会很危险,但 systemd 可以使用DynamicUser=.

[Service]
Type=simple
ExecStart=/usr/bin/python3
StandardInput=socket
DynamicUser=yes

如果您希望在客户端确认连接已建立,也许可以考虑使用cat.首先创建一些样板文本:

echo "established" > /usr/local/etc/simple/start_text

然后告诉 systemd 对该文本进行 cat 处理,然后是 stdin

[Service]
Type=simple
ExecStart=-cat /usr/local/etc/simple/start_text -
StandardInput=socket

现在,netcat当连接建立时,您的客户端将获得打印输出。

还值得注意的是,您应该使用Accept=yes[email protected]。否则,systemd 将期望您的应用程序可以接受传入连接,但这里的情况并非如此。

相关内容