在 gnome-shell 会话中自动将 systemd 控制组资源限制应用于特定用户应用程序

在 gnome-shell 会话中自动将 systemd 控制组资源限制应用于特定用户应用程序

看到这个GNOME 现在在 systemd 范围内启动应用程序我一直在寻找一种方法来让 systemd 将一些 cgroup 资源和内存限制应用到我的浏览器。

我想将MemoryMaxand应用CPUShareapp-gnome-firefox-*.scope每个的所有实例systemd.resource-control

但是 GNOME 没有使用实例化单元格式启动 Firefox [email protected],所以我不知道如何制作一个可自动应用于所有app-gnome-firefox-*.scope实例的 systemd 单元文件。

systemctl set-property --user app-gnome-firefox-92450.scope例如,一旦设备启动,我就可以手动将资源限制应用于实例,但这很麻烦。

有没有办法通过名称模式匹配来为瞬态范围注入属性?

这实际上并不是gnome-shell具体的;它同样适用于使用 调用命令的用户终端会话systemd-run --user --scope

细节

Firefox 确实是在 systemd 范围内启动的,并且它有自己的 cgroup:

$ systemctl --user status app-gnome-firefox-92450.scope
● app-gnome-firefox-92450.scope - Application launched by gnome-shell
     Loaded: loaded (/run/user/1000/systemd/transient/app-gnome-firefox-92450.scope; transient)
  Transient: yes
     Active: active (running) since Wed 2021-03-31 09:44:30 AWST; 32min ago
      Tasks: 567 (limit: 38071)
     Memory: 2.1G
        CPU: 5min 39.138s
     CGroup: /user.slice/user-1000.slice/[email protected]/app-gnome-firefox-92450.scope
             ├─92450 /usr/lib64/firefox/firefox
             ....
  ....

经核实

$ systemd-cgls --user-unit app-gnome-firefox-92450.scope
Unit app-gnome-firefox-92450.scope (/user.slice/user-1000.slice/[email protected]/app-gnome-firefox-92450.scope):
├─92450 /usr/lib64/firefox/firefox
...

$ ls -d /sys/fs/cgroup/user.slice/user-1000.slice/[email protected]/app-gnome-firefox-*
/sys/fs/cgroup/user.slice/user-1000.slice/[email protected]/app-gnome-firefox-92450.scope

我可以将MemoryMax(cgroup v2 约束memory.max)应用于已经运行的实例,systemctl set-property并且它会生效:

$ systemctl set-property --user app-gnome-firefox-98883.scope MemoryMax=5G
$ systemctl show --user app-gnome-firefox-98883.scope |grep ^MemoryMax
MemoryMax=5368709120
$ cat /sys/fs/cgroup/user.slice/user-1000.slice/[email protected]/app-gnome-firefox-*/memory.max
5368709120

它肯定会起作用 - 设置较低的MemoryMaxlike100M会导致 Firefox 范围 OOM,如中所见journalctl --user -u app-gnome-firefox-98883.scope

问题是我不知道如何systemd.resource-control自动应用规则新实例的应用程序。

我尝试创建一个包含.config/systemd/user/[email protected]

[Scope]
MemoryMax = 5G

但似乎没有效果。

systemd-analyze verify对此感到十分无助:

$ systemd-analyze  verify --user .config/systemd/user/[email protected] 
Failed to load unit file /home/craig/.config/systemd/user/[email protected]: Invalid argument

systemctl set-property --user app-gnome-firefox-92450.scope如果我在正在运行的实例上使用,systemctl --user show app-gnome-firefox-92450.scope我会在以下位置看到插入文件:

FragmentPath=/run/user/1000/systemd/transient/app-gnome-firefox-98883.scope
DropInPaths=/run/user/1000/systemd/transient/app-gnome-firefox-98883.scope.d/50-MemoryMax.conf

Names包含 pid,因此无法轻易匹配:

Id=app-gnome-firefox-98883.scope
Names=app-gnome-firefox-98883.scope

我有点不知所措。非常希望得到建议,但愿不是“gnome-shell 做错了,修补它”这样的建议。一些systemd 文档草稿建议使用其中一种可接受的模式。

解决方法 1 -systemd-run

到目前为止我看到的唯一解决方法是自己启动 Firefox 实例systemd-run

systemd-run --user --scope -u firefox.scope -p 'MemoryMax=5G' -p 'CPUQuota=80%' /usr/lib64/firefox/firefox

并让其成为控制进程。但这似乎以某种方式隔离了 Firefox 控制通道,从而阻止firefox其他应用程序或桌面会话启动的进程与 cgroup 范围内的 Firefox 通信,导致

Firefox 已在运行,但无响应。要使用 Firefox,您必须先关闭现有的 Firefox 进程、重启设备或使用其他配置文件。

编辑:Firefox 远程处理在通过手动启动时,可以通过在环境中为我的用户会话和选项进行systemd-run设置来修复。这可能是因为我使用的是 Wayland。一位同事报告说,使用 XOrg 和较旧的系统,它只对他们有效MOZ_DBUS_REMOTE-E MOZ_DBUS_REMOTE=1systemd-run没有 MOZ_DBUS_REMOTE=1

解决方法 2 - 作为用户服务

我最终为 Firefox 定义了一个 systemd 服务。

$ systemctl --user edit --full --force firefox.service
[Unit]
Description=Run Firefox

[Service]
ExecStart=/usr/lib64/firefox/firefox
Environment=MOZ_DBUS_REMOTE=1
MemoryMax = 5G
CPUQuota=400%

[Install]
WantedBy=gnome-session-initialized.target
systemctl --user  enable firefox.service

这将在登录时启动 Firefox,并配置所需的 cgroup 等。新firefox命令将在自动启动的实例中打开选项卡。我想现在就这样吧。

更好的选择?

仍然是一个笨拙的解决方法 - 它肯定可以通过以下方式将资源控制规则应用于切片.config/systemd/user

相关内容