Linux Control Groups, commonly referred to as cgroups, is a feature in the Linux kernel that provides a way to organise and manage system resources for processes. It allows you to allocate and limit resources like CPU, memory, and I/O bandwidth among different processes or groups of processes.
There are two versions of cgroups, the original version 1 and the unified
, version 2.
cgexec is a Bash script that allows users to execute a command within a cgroup, providing control over resource limits such as CPU, I/O, and memory.
The script requires v2/unified cgroups to function.
Documentation is available at https://wiki.tnonline.net/w/Linux/cgexec.
Attaches a program <cmd> to a unified cgroup with defined limits.
Usage: cgexec [options] <cmd> [cmd args]
Options:
-c cpu.weight (0-10000) Set CPU priority
-C cpu.max (1-100) Set max CPU time in percent
-i io.weight (1-10000) Set I/O weight
-m memory.high (0-max) Set soft memory limit
-M memory.max (0-max) Set hard memory limit
-g group Create or attach to existing cgroup. Default is to use an ephemeral group
-b path Use <path> as cgroup root
Requires Linux Control Groups v2 mounted at <path>.
Execute a command with default settings
cgexec echo "Hello, cgroups!"
Limit CPU and memory for a command
cgexec -c 50 -m 1G my_command
Attach to an existing cgroup
cgexec -g mygroup my_command
Use a custom cgroup root
cgexec -b /sys/fs/cgroup/mysubsystem my_command
It is possible to allow normal users to create their own cgroups by creating an initial cgroup container that is owned by the user.
First set up a container for the user
mkdir -p /sys/fs/cgroup/user/forza/main
echo "+cpu +memory +io" > /sys/fs/cgroup/user/cgroup.subtree_control
echo "+cpu +memory +io" > /sys/fs/cgroup/user/forza/cgroup.subtree_control
chown forza:forza /sys/fs/cgroup/user/forza
chown forza:forza /sys/fs/cgroup/user/forza/cgroup.procs
chown forza:forza /sys/fs/cgroup/user/forza/cgroup.threads
chown -R forza:forza /sys/fs/cgroup/user/forza/main
chmod 775 /sys/fs/cgroup/user/forza
chmod 775 /sys/fs/cgroup/user/forza/main
User <forza>
can now create new nested cgroups in /sys/fs/cgroup/user/forza
and attach processes to it.
The catch-22 of cgroups is that all programs by default reside in in the root /sys/fs/cgroup/cgroup.procs
, and even though a user can write to its own cgroup, they can not remove themselves from the root cgroup.
One solution is to let the user start a screen
or tmux
session and then use root/sudo to move it to the user's cgroup.
Then as root, check what pids
belong to the uaer session and add them to the user cgroup:
# ps af -u forza
5309 pts/0 S+ 0:00 | \_ screen
5310 ? Ss 0:00 | \_ SCREEN
5311 pts/1 Ss 0:00 | \_ -/bin/bash
5483 pts/1 R+ 0:00 | \_ ps af -u forza
# echo 5309 > /sys/fs/cgroup/user/forza/main/cgroup.procs
# echo 5310 > /sys/fs/cgroup/user/forza/main/cgroup.procs
# echo 5311 > /sys/fs/cgroup/user/forza/main/cgroup.procs
Now, the user's screen session is in the main
cgroup and the user can create additional cgroups and move processes started from within this session to that cgroup.
The user_cgroup
helper utility can automate the process of setting of user cgroups.
user_cgroup.initd
is an OpenRC init script that creates a cgroup hierarchy for specified users.user_cgroup.confd
is the configuration file for OpenRC.user_cgroup.sudoersd
is a sudo config file for allowing users to use theuser_cgroup
utility.user_cgroup
small tool to move a uaer's shell to the user cgroup.
The sudo file is optional, but allows a user to put the script in ~/.bash_profile
for automatic use.
Once installed, a user can simply run user_cgroup
to move itselslf to the user cgroup. Now it is possible for the user to create its own sub cgroups with cgexec
.
# ./cgexec ls -l
* Creating cgroup: /sys/fs/cgroup/user/forza/cmd-GEP0
* Executing: ls -l
total 60
-rwxr-xr-x 1 forza forza 4402 Dec 17 14:20 cgexec
-rw-r--r-- 1 forza forza 34580 Dec 16 19:02 LICENSE
drwxr-xr-x 1 forza forza 72 Dec 16 21:16 openrc
-rw-r--r-- 1 forza forza 4106 Dec 17 13:57 README.md
-rwxr-xr-x 1 forza forza 315 Dec 17 13:37 user_cgroup
-rw-r--r-- 1 forza forza 79 Dec 17 13:40 user_cgroup.sudoersd
* Cleaning up cgroup /sys/fs/cgroup/user/forza/cmd-GEP0