99 lines
1.8 KiB
Bash
99 lines
1.8 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# elevate once, then never again
|
|
if (( EUID != 0 )); then
|
|
exec sudo -p "Password: " "$0" "$@"
|
|
fi
|
|
|
|
PROG=$(basename "$0")
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Usage: $PROG N|--reset
|
|
N Number of logical CPUs to keep online (integer >= 1)
|
|
--reset Bring all logical CPUs online
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
get_total_cpus() { nproc --all; }
|
|
|
|
set_cpu_online() {
|
|
local cpu=$1 val=$2
|
|
local f="/sys/devices/system/cpu/cpu${cpu}/online"
|
|
[[ -e $f ]] || return 0
|
|
local cur
|
|
cur=$(cat "$f" 2>/dev/null || echo "")
|
|
[[ $cur == "$val" ]] && return 0
|
|
printf '%s\n' "$val" >"$f" 2>/dev/null || \
|
|
echo "Warning: failed to set cpu${cpu} online=$val" >&2
|
|
}
|
|
|
|
reset_cpus() {
|
|
local total=$1
|
|
for ((i = 0; i < total; i++)); do
|
|
set_cpu_online "$i" 1
|
|
done
|
|
}
|
|
|
|
apply_target() {
|
|
local target=$1 total=$2
|
|
for ((i = 0; i < total; i++)); do
|
|
if ((i < target)); then
|
|
set_cpu_online "$i" 1
|
|
elif ((i > 0)); then
|
|
set_cpu_online "$i" 0
|
|
fi
|
|
done
|
|
}
|
|
|
|
list_online() {
|
|
local total=$1
|
|
local online=()
|
|
for ((i = 0; i < total; i++)); do
|
|
local f="/sys/devices/system/cpu/cpu${i}/online"
|
|
if [[ -e $f ]]; then
|
|
[[ $(cat "$f") == 1 ]] && online+=("$i")
|
|
else
|
|
online+=("$i")
|
|
fi
|
|
done
|
|
echo "Online CPUs: ${online[*]}"
|
|
}
|
|
|
|
main() {
|
|
local total
|
|
total=$(get_total_cpus)
|
|
|
|
if [[ $# -ne 1 ]]; then
|
|
usage
|
|
fi
|
|
|
|
case $1 in
|
|
--reset)
|
|
reset_cpus "$total"
|
|
echo "Done."
|
|
;;
|
|
[0-9]*)
|
|
local target=$1
|
|
if ((target <= 0)); then
|
|
echo "Warning: minimum of 1 CPU required; using 1." >&2
|
|
target=1
|
|
fi
|
|
if ((target >= total)); then
|
|
reset_cpus "$total"
|
|
echo "Done."
|
|
else
|
|
apply_target "$target" "$total"
|
|
list_online "$total"
|
|
fi
|
|
;;
|
|
*)
|
|
usage
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|
|
|