病情描述

病情描述

病情描述

我在 Ubuntu 18.04.3 LTS 上使用 systemd 和 ssh 遇到了奇怪的情况

我检查了设备的状态ssh.socket

$ systemctl status ssh.socket
● ssh.socket - OpenBSD Secure Shell server socket
   Loaded: loaded (/lib/systemd/system/ssh.socket; disabled; vendor preset: enabled)
   Active: inactive (dead)
   Listen: [::]:22 (Stream)
 Accepted: 0; Connected: 0

它处于非活动状态,但我同时使用 ssh 登录,并且服务本身正在运行,并且 SSH 的套接字和相应端口已打开:

$ lsof -P -i -n | grep sshd
sshd      26785            root    3u  IPv4 14858764      0t0  TCP 10.200.130.28:22->10.100.40.141:42188 (ESTABLISHED)
sshd      26875          xxx_root    3u  IPv4 14858764      0t0  TCP 10.200.130.28:22->10.100.40.141:42188 (ESTABLISHED)
sshd      63859            root    3u  IPv4   238437      0t0  TCP *:22 (LISTEN)
sshd      63859            root    4u  IPv6   238439      0t0  TCP *:22 (LISTEN)

所以我查看了 ssh.socket 的单元文件/lib/systemd/system/ssh.socket

[Unit]
Description=OpenBSD Secure Shell server socket
Before=ssh.service
Conflicts=ssh.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Socket]
ListenStream=22
Accept=yes

[Install]
WantedBy=sockets.target

由于该Before=ssh.service指令应该在 ssh 服务之前启动,并且该Conflicts=ssh.service指令将导致它在 ssh 服务启动时停止。

这解释了为什么它发生在单元文件方面,但提出了其他问题。

问题

为什么 ssh.socket 单元的非活动状态对实际的 ssh 套接字没有影响?

为什么维护者添加了该Conflict指令?例如,如果您检查docker.socket它的单元文件没有设置为与docker.service. sshd 的情况有何不同?

附加信息

我还在旧的 Fedora 30 工作站上检查了这一点。它具有相同的条件,但有细微的差别:它使用sshd.service和作为单元名称,并且单元文件中sshd.socket没有指令。Beforesshd.socket

在这两个系统上,我没有注意到这种情况造成的任何问题,我怀疑它有某种目的,但找不到。

答案1

systemd 套接字是一种特殊类型的单元,它使 systemd 自身绑定到端口(或其他资源,例如 unix 域套接字文件路径),并为任何连接生成一个新的服务实例。启用 ssh.service 后,其 sshd 会连续运行并绑定到套接字,如 lsof 所示。相反,启用 ssh.socket 意味着 sshd 不会连续运行,而是仅调用它的一个实例来处理一个客户端。相反,它会显示 systemd 正在侦听端口 22。由于 systemd 和 sshd 不能同时侦听同一端口,因此 ssh.socket 指定 ssh.service 存在冲突。

答案2

需要理解的重要一点是,您所看到的是“套接字”单元的一种特定用法,总共有http://0pointer.de/blog/projects/inetd.html

所以在 的具体情况下ssh.socket,这相当于旧式类似inetd的调用(核心套接字单元设置:)Accept=yes,其中端口 22 上的每个传入请求(由 systemd 管理)都会导致单独的启动[email protected] 实例

另请参阅 systemd.socket 手册页:https://www.freedesktop.org/software/systemd/man/systemd.socket.html

如果设置 Accept=yes,则服务模板[电子邮件受保护]必须存在,为每个传入连接实例化服务

所以,一共有两种不同的方式来启动 sshd:

  • ssh.servicesshd.service只是一个别名)启动主 sshd 进程,然后该进程处理所有传入连接、生成子进程等。
  • ssh.socket+ [email protected],这里 systemd 将来自套接字管理端口的每个传入连接连接到一个新实例[电子邮件受保护],inetd 风格。这就是为什么在模板服务中,StandardInput=socket、 和ExecStart=/usr/sbin/sshd-i选项。

显然,一次只能使用一种方法,因此Conflicts=请确保两种方法不会同时运行。 (顺便说一句:该节的实际位置Conflicts=并不重要,可以在 ssh.service 中编写等效的一节,但一个就足够了)

相关内容