lonix Asked: 2018-09-24 06:23:49 +0800 CST2018-09-24 06:23:49 +0800 CST 2018-09-24 06:23:49 +0800 CST 空闲时间后停用 systemd 服务 772 我希望服务按需启动,而不是在启动时启动。为此,我可以使用 systemd 套接字激活(使用服务和套接字文件)。 但这是一个资源有限的服务器,所以在一段时间(例如 1 小时)不活动后,我想停止服务(直到它再次被触发)。我怎样才能做到这一点? 我查看了一些文档,但我无法确定这是否受支持。 更新: 假设这是不受支持的,用例可能仍然很常见。什么是实现这一目标的好方法/解决方法? linux systemd 3 个回答 Voted Best Answer TooTea 2018-09-27T16:37:04+08:002018-09-27T16:37:04+08:00 systemd 中的套接字激活可以在两种模式下工作: Accept=true: systemd 保持监听套接字,接受每个传入的连接,为每个连接生成一个新进程并将已建立的套接字传递给它。这种情况是微不足道的(每个进程在完成后退出)。 Accept=false: systemd 创建监听套接字并监视它的传入连接。一旦有人进来,systemd 就会生成服务并将侦听套接字传递给它。然后服务接受传入连接和任何后续连接。Systemd 不再跟踪套接字上发生的事情,因此它无法检测到不活动。 在后一种情况下,我认为唯一真正干净的解决方案是修改应用程序,使其在空闲一段时间后退出。如果你不能这样做,一个粗略的解决方法可能是设置 cron 或 systemd 计时器来每小时终止一次服务。如果服务只是很少产生,这可能是一个合理的近似值。 请注意,用例可能非常罕见。位于 poll()/select() 中等待连接的进程不会消耗任何 CPU 时间,因此在这种情况下使用的唯一资源是内存。仅设置一些交换并让内核决定是否值得将进程始终保留在 RAM 中可能更容易也更有效。 Rodney L. 2022-05-04T02:21:57+08:002022-05-04T02:21:57+08:00 如果您无法调整程序的主循环以使其在一段时间后没有套接字活动而退出,那么您可以使用systemd-socket-proxyd,它确实有一个空闲超时选项。 假设您的服务被调用thing.service。它正在监听LISTEN_ADDR。您将添加一个服务,该服务位于LISTEN_ADDR和PRIVATE_LISTEN_ADDRthing.socket之间并将thing.service连接转发。 调整配置thing以监听PRIVATE_LISTEN_ADDR而不是LISTEN_ADDR。这可能在 中完成thing.service,或者可能在thing.conf- 这取决于应用程序。 如果没有其他单元依赖于它,请将您的服务配置为停止。这可以通过StopWhenUnneeded=true在文件的[Unit]部分中进行设置来完成thing.service。 添加thing-proxy.service. 这会thing.service通过PRIVATE_LISTEN_ADDR建立连接。我们在这里将空闲超时配置为 10 分钟。 [Unit] Requires=thing.service After=thing.service Requires=thing.socket After=thing.socket [Service] ExecStart=/usr/lib/systemd/systemd-socket-proxyd --exit-idle-time=10min PRIVATE_LISTEN_ADDR PrivateTmp=yes PrivateNetwork=yes 调整thing.socket使其开始thing-proxy.service而不是thing.service: [Socket] Accept=false ListenStream=LISTEN_ADDR Service=thing-proxy.service [Install] WantedBy=sockets.target LISTEN_ADDR和PRIVATE_LISTEN_ADDR的值可以hostname:port用于 TCP 服务或 UNIX 域套接字路径,或者两者都可以,这取决于您想要什么以及应用程序可以做什么。它们只需要不同的地址,因为现在您有两个进程正在侦听连接。 Alexander 2018-09-27T08:16:48+08:002018-09-27T08:16:48+08:00 如果您的服务能够被套接字激活,那么您可以Accept=yes在套接字单元中使用。然后将为每个连接执行一个新的服务实例,并在套接字关闭时停止。
systemd 中的套接字激活可以在两种模式下工作:
Accept=true
: systemd 保持监听套接字,接受每个传入的连接,为每个连接生成一个新进程并将已建立的套接字传递给它。这种情况是微不足道的(每个进程在完成后退出)。Accept=false
: systemd 创建监听套接字并监视它的传入连接。一旦有人进来,systemd 就会生成服务并将侦听套接字传递给它。然后服务接受传入连接和任何后续连接。Systemd 不再跟踪套接字上发生的事情,因此它无法检测到不活动。在后一种情况下,我认为唯一真正干净的解决方案是修改应用程序,使其在空闲一段时间后退出。如果你不能这样做,一个粗略的解决方法可能是设置 cron 或 systemd 计时器来每小时终止一次服务。如果服务只是很少产生,这可能是一个合理的近似值。
请注意,用例可能非常罕见。位于 poll()/select() 中等待连接的进程不会消耗任何 CPU 时间,因此在这种情况下使用的唯一资源是内存。仅设置一些交换并让内核决定是否值得将进程始终保留在 RAM 中可能更容易也更有效。
如果您无法调整程序的主循环以使其在一段时间后没有套接字活动而退出,那么您可以使用
systemd-socket-proxyd
,它确实有一个空闲超时选项。假设您的服务被调用
thing.service
。它正在监听LISTEN_ADDR。您将添加一个服务,该服务位于LISTEN_ADDR和PRIVATE_LISTEN_ADDRthing.socket
之间并将thing.service
连接转发。调整配置
thing
以监听PRIVATE_LISTEN_ADDR而不是LISTEN_ADDR。这可能在 中完成thing.service
,或者可能在thing.conf
- 这取决于应用程序。如果没有其他单元依赖于它,请将您的服务配置为停止。这可以通过
StopWhenUnneeded=true
在文件的[Unit]
部分中进行设置来完成thing.service
。添加
thing-proxy.service
. 这会thing.service
通过PRIVATE_LISTEN_ADDR建立连接。我们在这里将空闲超时配置为 10 分钟。调整
thing.socket
使其开始thing-proxy.service
而不是thing.service
:LISTEN_ADDR和PRIVATE_LISTEN_ADDR的值可以
hostname:port
用于 TCP 服务或 UNIX 域套接字路径,或者两者都可以,这取决于您想要什么以及应用程序可以做什么。它们只需要不同的地址,因为现在您有两个进程正在侦听连接。如果您的服务能够被套接字激活,那么您可以
Accept=yes
在套接字单元中使用。然后将为每个连接执行一个新的服务实例,并在套接字关闭时停止。