Systemd 似乎不尊重 After= 依赖性?

Systemd 似乎不尊重 After= 依赖性?

我有一个 PostgreSQL 服务器(postgresql.service)和一个基本的 shell 脚本(mobilizon-postgresql.service运行该脚本是为了向第三个服务(Mobilizon)提供有关数据库的一些断言)。

因此很自然地,mobilizon-postgresql.service配置了以下After=依赖项postgresql.service

# systemctl show mobilizon-postgresql.service | grep After=
After=basic.target system.slice systemd-journald.socket sysinit.target postgresql.service

虽然重新配置系统之后(没有触及这些依赖关系),但我在日志中看到以下行为:

1677672119.103035 myserver systemd[1]: Starting Mobilizon PostgreSQL setup...
...
1677672119.153192 myserver systemd[1]: Starting PostgreSQL Server...

那么,mobilizon-postgresql.service开始了的启动postgresql.service

1677672119.279742 myserver mobilizon-postgresql-start[329444]: psql: error: could not connect to server: No such file or directory
1677672119.279742 myserver mobilizon-postgresql-start[329444]:         Is the server running locally and accepting
1677672119.279742 myserver mobilizon-postgresql-start[329444]:         connections on Unix domain socket "/run/postgresql/.s.PGSQL.543>
1677672119.283558 myserver systemd[1]: mobilizon-postgresql.service: Main process exited, code=exited, status=2/INVALIDARGUMENT
1677672119.283707 myserver systemd[1]: mobilizon-postgresql.service: Failed with result 'exit-code'.
1677672119.289678 myserver systemd[1]: Failed to start Mobilizon PostgreSQL setup.

因此当然mobilizon.postgresql无法建立与数据库的连接。

1677672119.503881 myserver postgres[329458]: [329458] LOG:  starting PostgreSQL 13.10 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 11>
1677672119.512541 myserver postgres[329458]: [329458] LOG:  listening on IPv4 address "0.0.0.0", port 5432
1677672119.512863 myserver postgres[329458]: [329458] LOG:  listening on IPv6 address "::", port 5432
1677672119.519498 myserver postgres[329458]: [329458] LOG:  listening on Unix socket "/run/postgresql/.s.PGSQL.5432"
...
1677672119.871989 myserver systemd[1]: Started PostgreSQL Server.

后来才有postgresql.service报道称该项目已全面启动。

这种行为完全违背了我对的理解After=。来自systemd.unit(5)

如果单元 foo.service 包含设置 Before=bar.service 且两个单元都在启动,则 bar.service 的启动将延迟,直到 foo.service 完成启动。

我在这儿有错误的假设吗?

Systemd 版本为 251.12,发行版为 NixOS 22.11

答案1

man systemd.unitsystemd 所说的“启动完成”是什么意思?

对于服务单元来说,当所有配置的启动命令都已调用,并且它们失败或报告启动成功时,即认为服务单元的启动已完成,以 Before=/After= 为目的。

因此,您需要查看 postgresql 服务文件,看看它是否正在执行诸如分叉并将其 pid 放入文件中之类的操作,或者sd_notify()在其代码中使用来发出“就绪”信号。这没什么用。

遗憾的是,解决这个问题的简单方法是让服务mobilizon-postgresql 等待 Unix 域套接字存在,使用inotifywait或类似方法,或者添加Restart=on-failure并重RestartSec=1试直到成功。

Systemd 的工作方式是创建一个套接字单元,每当有人尝试打开该套接字时,您都会启动一个程序。在本例中,通过启动打开套接字的脚本,它会启动 postgresql。

答案2

(顺便说一句,显示完整的单位会很有帮助)

After=不带Wants=Requires=没有达到您认为的效果。如man systemd.unit所述(关于Before=, After=):

注意这些设置与需求依赖关系独立且正交Requires=由、Wants=Requisite=或进行配置。在和选项BindsTo=中同时包含单元名称是一种常见模式,在这种情况下,列出的单元将在使用这些选项配置的单元之前启动。After=Wants=

(海报重点标注)

相关内容