cgroups script for the current session

In Linux, cgroups (a kernel feature) allows to limit the resources (cpu, memory…) accessible to a group of processes. I have written a little bash script that will either:

  • create some groups for the current user session and assign some restrictions. No need to be root or to modify a global configuration file. Call it when your desktop session starts (for example by putting an entry in «~/.kde/Autostart»). Edit the script to create your own groups.
  • start a process in one of theses groups

The main reason was that I encountered a bug with Firefox and Google+, with triggered infinite memory allocation, which freezes my machine for a few minutes (because of the trashing). I hope that it will allow me to kill the process/close the tabs if it happens again.

I only tested it in Ubuntu 14.04, so it may require some adaptations for other Linux systems. When a user logs in, a cgroup group is created for the user session, and only the configuration at the session level (/sys/fs/cgroup/*/user/USER_ID.user/SESSION_ID.session) can be modified by the user. So this script will create sub-groups under this session level.

Here is the script: mycgroup.sh (please rename it after download). Some usage examples:

# create the groups
mycgroup init
# run in the groups "darktable" the command "darktable"
mycgroup run darktable darktable

Content of the script (edit it and define your own groups):

#!/bin/bash
 
# Create a group
# param:
# - type(s) (cpu, memory)
# - group path
function mycg_create {
    GRP=$(id -g -n)
    cgcreate -t $USER:$GRP -a $USER:$GRP -g "$1":"$2"
}
 
# Format a group path for the current session of the current user
# param: group name
function mycg_path {
    echo -n user/$UID.user/"$XDG_SESSION_ID".session/"$1"
}
 
# Initialize my groups
function mycg_init {
    echo Init cgroups: $(mycg_path)
    DARKTABLE=$(mycg_path darktable)
    mycg_create "cpu,memory" "$DARKTABLE"
   
    # Limit a bit the memory for darktables
    echo $((1500*1024*1024)) > /sys/fs/cgroup/memory/"$DARKTABLE"/memory.limit_in_bytes
    echo 900 > /sys/fs/cgroup/cpu/"$DARKTABLE"/cpu.shares
    
    # A group for Firefox
    GOOGLEFOX=$(mycg_path googlefox)
    mycg_create "cpu,memory" "$GOOGLEFOX"
    
    echo $((800*1024*1024)) > /sys/fs/cgroup/memory/"$GOOGLEFOX"/memory.limit_in_bytes
    echo 500 > /sys/fs/cgroup/cpu/"$GOOGLEFOX"/cpu.shares
}
 
if [ "$1" == "init" ]
then
    mycg_init
elif [ "$1" == "run" ]
then
    shift
    if [ "$#" -lt 2 ]
    then
        echo "Error: not enough args"
        echo "mygroup exec PROFILE_NAME COMMAND"
        exit 1
    fi
    CG_GRP="$1"
    shift 
    echo "Execute: group=$CG_GRP, command=$@"
    CG_PATH=$(mycg_path "$CG_GRP")
    cgexec -g memory,cpu:"$CG_PATH" "$@"
else
    echo "Unknown command: $1"
    exit 2
fi

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *