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 Answer
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
│ ├─user@1000.service
.....
│ └─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 user@1000.service
(where 1000 - is a UID) with slightly bigger limit. This way you will always have resources available for system daemons.
-
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.– derobertOct 18, 2019 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 Jul 23, 2020 at 14:07