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,Distro 是 NixOS 22.11

答案1

systemd 「啟動完成」是什麼意思?man systemd.unit

對於服務單元,當所有配置的啟動命令都已被呼叫並且它們失敗或報告啟動成功時,出於 Before=/After= 的目的,啟動被視為已完成。

因此,您需要查看 postgresql 服務文件,看看它是否正在執行諸如 fork 並將其 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=,在這種情況下,列出的單元將在配置了這些選項的單元之前啟動。

(重點由海報添加)

相關內容