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

Cra*_*ger 7 linux gnome cgroup systemd

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

\n

我想将 aMemoryMax和应用于每个CPUShare的所有app-gnome-firefox-*.scope实例systemd.resource-control

\n

但 GNOME 不会使用实例化的单元格式启动 Firefox app-gnome-firefox-@.scope,因此我不知道如何创建一个自动应用于所有app-gnome-firefox-*.scope实例的 systemd 单元文件。

\n

我可以在单元启动后手动将资源限制应用于实例systemctl set-property --user app-gnome-firefox-92450.scope(例如),但这很痛苦。

\n

有没有办法通过名称模式匹配来注入瞬态作用域的属性?

\n

这并不gnome-shell具体;它也适用于调用命令的用户终端会话systemd-run --user --scope

\n

细节

\n

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

\n
$ systemctl --user status app-gnome-firefox-92450.scope\n\xe2\x97\x8f app-gnome-firefox-92450.scope - Application launched by gnome-shell\n     Loaded: loaded (/run/user/1000/systemd/transient/app-gnome-firefox-92450.scope; transient)\n  Transient: yes\n     Active: active (running) since Wed 2021-03-31 09:44:30 AWST; 32min ago\n      Tasks: 567 (limit: 38071)\n     Memory: 2.1G\n        CPU: 5min 39.138s\n     CGroup: /user.slice/user-1000.slice/user@1000.service/app-gnome-firefox-92450.scope\n             \xe2\x94\x9c\xe2\x94\x8092450 /usr/lib64/firefox/firefox\n             ....\n  ....\n
Run Code Online (Sandbox Code Playgroud)\n

经核实

\n
$ systemd-cgls --user-unit app-gnome-firefox-92450.scope\nUnit app-gnome-firefox-92450.scope (/user.slice/user-1000.slice/user@1000.service/app-gnome-firefox-92450.scope):\n\xe2\x94\x9c\xe2\x94\x8092450 /usr/lib64/firefox/firefox\n...\n
Run Code Online (Sandbox Code Playgroud)\n

\n
$ ls -d /sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app-gnome-firefox-*\n/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app-gnome-firefox-92450.scope\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
$ systemctl set-property --user app-gnome-firefox-98883.scope MemoryMax=5G\n$ systemctl show --user app-gnome-firefox-98883.scope |grep ^MemoryMax\nMemoryMax=5368709120\n$ cat /sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app-gnome-firefox-*/memory.max\n5368709120\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

问题是我无法弄清楚如何自动为应用程序的新实例systemd.resource-control应用规则。

\n

我尝试创建一个.config/systemd/user/app-gnome-firefox-@.scope包含

\n
[Scope]\nMemoryMax = 5G\n
Run Code Online (Sandbox Code Playgroud)\n

但似乎没有效果。

\n

systemd-analyze verify窒息而无济于事:

\n
$ systemd-analyze  verify --user .config/systemd/user/app-gnome-firefox-@.scope \nFailed to load unit file /home/craig/.config/systemd/user/app-gnome-firefox-@i.scope: Invalid argument\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
FragmentPath=/run/user/1000/systemd/transient/app-gnome-firefox-98883.scope\nDropInPaths=/run/user/1000/systemd/transient/app-gnome-firefox-98883.scope.d/50-MemoryMax.conf\n
Run Code Online (Sandbox Code Playgroud)\n

Names包含了 pid,所以不能轻易匹配:

\n
Id=app-gnome-firefox-98883.scope\nNames=app-gnome-firefox-98883.scope\n
Run Code Online (Sandbox Code Playgroud)\n

我有点困惑。非常感谢您的建议,希望不是“gnome-shell 做错了,修补它”的建议。一些systemd 文档草案表明它正在使用一种可接受的模式。

\n

解决方法 1 -systemd-run

\n

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

\n
systemd-run --user --scope -u firefox.scope -p \'MemoryMax=5G\' -p \'CPUQuota=80%\' /usr/lib64/firefox/firefox\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
\n

Firefox 已在运行,但没有响应。要使用 Firefox,您必须首先关闭现有的 Firefox 进程、重新启动设备或使用不同的配置文件。

\n
\n

编辑:通过手动启动时的 Firefox 远程处理通过systemd-runMOZ_DBUS_REMOTE环境中为我的用户会话和-E MOZ_DBUS_REMOTE=1作为systemd-run. 可能是因为我正在使用 Wayland。一位同事报告说,使用 XOrg 和旧系统只能在没有 MOZ_DBUS_REMOTE=1.

\n

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

\n

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

\n
$ systemctl --user edit --full --force firefox.service\n
Run Code Online (Sandbox Code Playgroud)\n
[Unit]\nDescription=Run Firefox\n\n[Service]\nExecStart=/usr/lib64/firefox/firefox\nEnvironment=MOZ_DBUS_REMOTE=1\nMemoryMax = 5G\nCPUQuota=400%\n\n[Install]\nWantedBy=gnome-session-initialized.target\n
Run Code Online (Sandbox Code Playgroud)\n
systemctl --user  enable firefox.service\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

更好的选择?

\n

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

\n