Skip to content

Instantly share code, notes, and snippets.

@nikhilm
Created October 27, 2022 15:58
Show Gist options
  • Save nikhilm/0282591e3c3b1472f9cfa84e04059f62 to your computer and use it in GitHub Desktop.
Save nikhilm/0282591e3c3b1472f9cfa84e04059f62 to your computer and use it in GitHub Desktop.
Run a process in a cgroupv1 to limit CPU and memory usage. Useful for Ubuntu Bionic
#!/bin/bash
# All credit for figuring out these incantations goes to https://utcc.utoronto.ca/~cks/space/blog/linux/CgroupsForMemoryLimiting
#
# Script to run a command in a v1 cgroup limiting CPU and memory.
# Use as `./confine.sh command <other args>`.
# This is tested on Ubuntu Bionic.
# You will need to install the `cgroup-tools` package from `apt` first.
# Remember to tweak the limits based on your machine.
# `sudo` is required to create the cgroup, but the build itself is run as a normal user.
# CPU segmentation - limit processes to only these CPUs.
# I used this because cpu.shares didn't seem to work.
# On my machine with 12 cores, this leaves 4 cores free.
CPUS="0-7"
# Memory limit in GB
MEMORY_GB=20
# Group name
# If you ever need to delete the group, run `sudo cgdelete memory,cpuset:$CGROUP_NAME`
CGROUP_NAME=confine
# No changes necessary beyond here.
# Linux has cgroups v1 and v2. v2 is better, and systemd-run can directly use
# it, rendering this script redundant.
# However only v1 or v2 can be enabled at one time. Since Ubuntu uses v1 at
# boot, and a bunch of services are running, I believe we can't switch
# without a bunch of work. I am not entirely sure about this, but all I cared
# about was getting it working fast.
set -euo pipefail
# Create the cgroup, needs sudo.
sudo cgcreate -t "$USER" -a "$USER" -g "memory,cpuset:$CGROUP_NAME"
# Limit CPU
echo $CPUS > "/sys/fs/cgroup/cpuset/$CGROUP_NAME/cpuset.cpus"
# Needed, because Linux be Linux.
# https://stackoverflow.com/questions/37533173/getting-cgroup-change-of-group-failed-when-trying-to-add-process-to-cgroup
echo 0 > "/sys/fs/cgroup/cpuset/$CGROUP_NAME/cpuset.mems"
# Limit memory
echo $((MEMORY_GB * 1024 * 1024 * 1024)) > "/sys/fs/cgroup/memory/$CGROUP_NAME/memory.limit_in_bytes"
# Run
cgexec -g "memory,cpuset:$CGROUP_NAME" --sticky "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment