I want to reserve a small amount of cpu and memory to be able in case of emergency create tty session and kill a memory hogging X application. cgroups provide this functionality. How do I put all my X applications inside cgroup automatically?
1 Answers
I use Debian, so the solution is based on systemd cgroup implementation.
The first step is to inspect the cgroups hierarchy:
> systemd-cgls
-.slice
├─user.slice
│ └─user-1000.slice
│ ├─[email protected]
.....
│ └─session-2.scope
│ ├─1376 lightdm --session-child 14 21
│ ├─1400 x-window-manager
.....
systemd automatically assigns cgroups to terminal sessions. In cgroup hierarchy we need determine which session-*.scope has X applications in it. Default X session scope number is always the same.
To set memory limit to all programs in a scope, type
> systemctl set-property session-2.scope MemoryLimit=14G
This command sets memory limit to the session 2 until reboot.
To make this rule permanent, run
> sudo systemctl edit session-2.scope
in text editor type
[Scope]
MemoryLimit=14G
and save. This rule will persist between reboots. Other resource limits may be set in a same file.
Edit
As derobert pointed out, X session scope number is not guarantied to be the same. More robust solution is to determine this number at runtime.
File /usr/local/bin/resource_limit.sh:
#!/bin/bash
for s in $(systemd-cgls --no-pager --user-unit \
| grep --extended-regexp --only-matching \
'session-.{1,3}\.scope');do
systemctl set-property --runtime "$s" MemoryLimit="$1"
done
File /etc/systemd/system/resource_limit.service:
[Unit]
Description=Limit resources
Requires=multi-user.target
After=multi-user.target
[Service]
Type=oneshot
ExecStartPre=/bin/sleep 5
ExecStart=/usr/local/bin/resource_limit.sh 14G
ExecStop=/usr/local/bin/resource_limit.sh 20G
RemainAfterExit=true
[Install]
WantedBy=graphical.target
Copy files above to your system and issue command
systemctl daemon-reload
After this you may set specified limit (in this case 14G) using command
systemctl start resource_limit.service
and unset it (setting some higher limit value) using command
systemctl stop resource_limit.service
In order to run this script on reboot automatically, issue command
systemctl enable resource_limit.service
Note 1
If your X session does not start fast enough, you may want to increase service delay via ExecStartPre or enable service manually.
Note 2
It is a good idea to also add restrictions to [email protected] (where 1000 - is a UID) with slightly bigger limit. This way you will always have resources available for system daemons.
- 353
- 1
- 3
- 13
-
It's just session 2 because they're assigned in order. Here my X session is 4 (also Debian). So you unfortunately can't consistently target the X session by name. You can get a list of sessions from `loginctl list-sessions`, so I bet it's possible to do it with some scripting. – derobert Oct 18 '19 at 20:23
-
@derobert the command `loginctl --no-pager --no-legend --property=session list-sessions` should do what you desribe, but it looks like the CLI does not respect the `--property=` part – code_monk Jul 23 '20 at 14:07