Linux

如何從命令行為已存在的程序創建 systemd 範圍?

  • June 19, 2019

我有一台執行 cgroups v2(統一)層次結構的機器,因此 systemd 負責管理所有 cgroups 和委託給 systemd 使用者實例的工作。我想對一組程序執行資源控制,所以我需要將它們放在一個單元中——大概是一個systemd 範圍

通常,systemd-run會這樣做——但不幸的是,這些程序已經在執行,我不想重新啟動它們。

如何從現有流程中創建systemd 範圍?控制組介面文件告訴我這是可能的,但我無法從命令行找到方法。systemctl兩者似乎都systemd-run無法做到這一點。

有沒有辦法從命令行?如果重要,我正在執行 systemd v241。

有多種命令行工具可以進行 dbus 呼叫;systemd 自帶一個叫做busctl. 所以你可以StartTransientUnit從命令行呼叫。

命令

語法確實很煩人,但看起來像這樣(對於一個程序 ID,14460):

busctl call --user org.freedesktop.systemd1 /org/freedesktop/systemd1 \
      org.freedesktop.systemd1.Manager StartTransientUnit 'ssa(sv)a(sa(sv))' \
      'SCOPE-NAME.scope' fail 1 PIDs au 1 14460 0

解釋

這確實是不透明的(並且嘗試了一些嘗試來正確,並最終使用它dbus-monitor來查看它是如何systemd-run做到的——儘管僅在系統管理器上,systemd-run --user似乎沒有通過 dbus)。所以一個解釋,一個參數一個參數:

busctl call --user                  # use user session dbus, not system   
 org.freedesktop.systemd1          # dbus service name
 /org/freedesktop/systemd1         # dbus object in that service
 org.freedesktop.systemd1.Manager  # interface name in that service 
 StartTransientUnit                # method we're going to call
 'ssa(sv)a(sa(sv))'                # signature of method, see below
 'SCOPE-NAME.scope'                # first argument, name of scope
 fail                              # second argument, how to handle conflicts (see below)
 1                                 # start of third argument, number of systemd properties for unit 
 PIDs                              # name of first property
 au                                # data type of first property, (a)rray [aka list] of (u)nsigned integers
 1                                 # count of array — that is, number of pids 
 14460                             # first pid
 0                                 # fourth argument: array size=0 (unused parameter)

添加到命令

更多樓盤

要將另一個 systemd 屬性添加到單元中,您需要增加屬性的數量並添加它。請注意,每個屬性至少是三個附加的命令行參數:鍵、值類型和值。例如,添加 Slice 屬性將來自:

… fail 1 PIDs au 1 14460 0

… fail 2 PIDs au 1 14460 Slice s whatever.slice 0
      ^                 ^^^^^ ^ ^^^^^^^^^^^^^^
    count                key type value

類型“s”是字元串。它們的列表可以在D-Bus 規範的“類型系統”一章中找到

您當然可以將計數更改為 3 並添加第三個屬性。等等。

更多 pid

類似於更多屬性,但這次是隱藏在“PIDs”屬性值中的計數。一個例子應該更清楚:

… fail 1 PIDs au 1 14460 0

變成

… fail 1 PIDs au 2 14460 14461 0
                ^       ^^^^^
        internal count  second pid

如果您添加 PID 14461 和 14460。

您可以以相同的方式添加第三個、第四個等 PID。

結合它們

您當然可以將其他屬性與其他 pid 結合起來。請記住,pids 列表是一個屬性值,因此它需要保持在一起。您不能將 pid 參數與其他屬性混合使用。正確的方法是改變:

… fail 1 PIDs au 1 14460 0

到:

… fail 2 PIDs au 2 14460 14461 Slice s whatever.slice 0

(順序無關緊要,您可以將 Slice 塊放在 PIDs 塊之前)。

簽名從哪裡來?

簽名可以從systemd dbus API 文件中獲得,或者可能更容易通過使用 dbus 內省獲得:

$ busctl introspect org.freedesktop.systemd1 /org/freedesktop/systemd1 \
        org.freedesktop.systemd1.Manager | grep1 StartTransientUnit
NAME                  TYPE     SIGNATURE         RESULT/VALUE   FLAGS
.StartTransientUnit   method   ssa(sv)a(sa(sv))  o              -

(對於grep1,請參閱https://unix.stackexchange.com/a/279518

列出了很多方法和 dbus 屬性,這裡有 180 多個。所以不要省略grep.

“失敗”處理衝突是什麼意思?那裡還有什麼?

根據systemd 文件(在“CreateUnit”下查看),有用的值是failreplacefail意味著如果發生衝突,您的範圍將無法啟動。replace意味著 systemd 將擺脫衝突的單元。請注意,這似乎僅適用於目前正在啟動或計劃的單元(它確實說“排隊”) - 例如,replace 不會用相同的名稱替換已經執行的範圍。

引用自:https://unix.stackexchange.com/questions/525740