11#! /usr/bin/env bash
2- set -euo pipefail
32
43# ----------------------------------------------------------
54# CPU isolation launcher for Linux (cgroup v1 & v2)
@@ -9,64 +8,82 @@ set -euo pipefail
98# 2. Validation: Ensures CPU_SET_NAME and CPU_SET_RANGE exist.
109# 3. Cgroup detection: Automatically handles v1 and v2.
1110# 4. CPU and memory configuration: Writes cpuset.cpus and cpuset.mems.
12- # 5. Associating the application:
13- # - $$ is the PID of the script itself.
14- # - When we exec "$@", the application replaces the script and inherits the cgroup.
15- # - This is the standard way to bind the app to the cpuset.
11+ # 5. Associating the application
1612# ----------------------------------------------------------
1713
18- # Validate environment variables
14+ set -euo pipefail
15+
16+ # validate required environment variables
1917: " ${CPU_SET_NAME:? Environment variable CPU_SET_NAME is required} "
2018: " ${CPU_SET_RANGE:? Environment variable CPU_SET_RANGE is required} "
2119echo " CPU isolation launcher starting..."
22- echo " CPU_SET_NAME = $CPU_SET_NAME "
23- echo " CPU_SET_RANGE = $CPU_SET_RANGE "
20+ echo " CPU_SET_NAME [$CPU_SET_NAME ]"
21+ echo " CPU_SET_RANGE [$CPU_SET_RANGE ]"
22+
23+ # check for root
24+ if [ " $EUID " -ne 0 ]; then
25+ echo " this script must be run as root."
26+ echo " try: sudo $0 "
27+ exit 1
28+ fi
2429
25- # Check for root privileges
26- if [[ $EUID -ne 0 ]]; then
27- echo " WARNING: root privileges are required for true CPU isolation."
28- echo " Proceeding without isolation..."
29- exec " $@ "
30+ if ! [[ $CPU_SET_RANGE =~ ^[0-9,-]+$ ]]; then
31+ echo " invalid CPU_SET_RANGE format. value [$CPU_SET_RANGE ]"
32+ exit 1
3033fi
3134
32- # Detect cgroup version
35+ # --- minimal NUMA check ---
36+ # nodes_used=$(for cpu in $(echo "$CPU_SET_RANGE" | sed 's/,/ /g'); do
37+ # for node_dir in /sys/devices/system/node/node*; do
38+ # grep -qE "(^|,)$cpu($|,|-)" "$node_dir/cpulist" && echo $(basename $node_dir | sed 's/node//')
39+ # done
40+ # done | sort -u)
41+ #
42+ # if [[ $(wc -w <<< "$nodes_used") -gt 1 ]]; then
43+ # echo "error: requested CPUs span multiple NUMA nodes. nodes [$nodes_used]"
44+ # exit 1
45+ # fi
46+ # echo "requested CPUs are within NUMA node. node [$nodes_used]"
47+ # --- end minimal NUMA check ---
48+
49+ # build path based on cgroup version
3350if [[ -f /sys/fs/cgroup/cgroup.controllers ]]; then
3451 CGROUP_VERSION=2
3552 BASE_CGROUP=" /sys/fs/cgroup"
3653else
3754 CGROUP_VERSION=1
3855 BASE_CGROUP=" /sys/fs/cgroup/cpuset"
3956fi
40- echo " Detected cgroup version: $CGROUP_VERSION "
41-
57+ echo " detected cgroup version. value [$CGROUP_VERSION ]"
4258GROUP_PATH=" $BASE_CGROUP /$CPU_SET_NAME "
4359
44- # Create cpuset directory if it doesn't exist
60+ # create cpuset directory if it doesn't exist
4561if [[ ! -d " $GROUP_PATH " ]]; then
4662 mkdir -p " $GROUP_PATH "
47- echo " Created cpuset directory: $GROUP_PATH "
63+ echo " created cpuset directory. path [ $GROUP_PATH ] "
4864fi
4965
50- # Write CPUs
66+ # write CPUs
5167CPU_FILE=" $GROUP_PATH /cpuset.cpus"
5268echo " $CPU_SET_RANGE " > " $CPU_FILE "
53- echo " Wrote CPUs to $CPU_FILE "
69+ echo " wrote CPUs to file. path [ $CPU_FILE ] "
5470
55- # Write memory nodes (required for cpuset)
71+ # write memory nodes (required for cpuset)
5672MEM_FILE=" $GROUP_PATH /cpuset.mems"
5773if [[ ! -f " $MEM_FILE " ]]; then
58- # assume NUMA node 0
59- echo " 0" > " $MEM_FILE "
74+ echo " $nodes_used " > " $MEM_FILE "
6075fi
61- echo " Set memory nodes in $MEM_FILE "
62-
63- # TODO(MILS): WARN ABOUT MULTI-NUMA CPU RANGES AND REFUSE TO CONTINUE
76+ echo " set memory nodes in file. path [$MEM_FILE ]"
6477
65- # Add current process to the cpuset
66- # - $$ is the PID of the script itself.
67- # - When we exec "$@", the application replaces the script and inherits the cgroup.
78+ # add current process to the cpuset
6879PROCS_FILE=" $GROUP_PATH /cgroup.procs"
80+ # NB: $$ is the PID of the script itself
6981echo " $$ " > " $PROCS_FILE "
70- echo " Added PID $$ to $PROCS_FILE "
71- echo " Launching application in isolated cpuset..."
72- exec " $@ "
82+ echo " added process to cpuset. PID [$$ ] path [$PROCS_FILE ]"
83+ echo " launching application in isolated cpuset..."
84+ # NB: when we exec "$@", the application replaces the script and inherits the cgroup
85+ " $@ "
86+ # print application return so that the script doesn't obfuscate it
87+ ret=$?
88+ echo " Application exited with code $ret "
89+ exit $ret
0 commit comments