看到这个GNOME 现在在 systemd 范围内启动应用程序我一直在寻找一种方法来让 systemd 将一些 cgroup 资源和内存限制应用到我的浏览器。
我想将MemoryMax
and应用CPUShare
到app-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
它肯定会起作用 - 设置较低的MemoryMax
like100M
会导致 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=1
systemd-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
?