Skip to content

Instantly share code, notes, and snippets.

@samueljon
Last active February 10, 2026 07:07
Show Gist options
  • Select an option

  • Save samueljon/e7818edeb218f5e2f1e3e258949d04c8 to your computer and use it in GitHub Desktop.

Select an option

Save samueljon/e7818edeb218f5e2f1e3e258949d04c8 to your computer and use it in GitHub Desktop.
Disable / Enable HyperThreading cores on runtime - linux
#!/bin/bash
HYPERTHREADING=1
TABLE_VIEW=0 # Default to list view
AUTO_MODE=0 # Automatic enable/disable without prompt
# Color codes
BOLD='\033[1m'
GREEN='\033[0;32m'
RED='\033[0;31m'
ORANGE='\033[0;33m'
RESET='\033[0m'
# Global arrays to cache topology information
declare -A CACHED_SIBLINGS # Maps thread ID to its sibling list
declare -A CACHED_SIBLING_MAP # Maps each thread to its sibling
declare -A CACHED_PRIMARY # Maps each thread to 1 if primary, 0 if HT sibling
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-t|--table)
TABLE_VIEW=1
shift
;;
-e|--enable)
AUTO_MODE=1
HYPERTHREADING=1
shift
;;
-d|--disable)
AUTO_MODE=1
HYPERTHREADING=0
shift
;;
-h|--help)
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " -e, --enable Enable hyperthreading and exit"
echo " -d, --disable Disable hyperthreading and exit"
echo " -t, --table Display threads in table format grouped by physical cores"
echo " -h, --help Show this help message"
echo ""
echo "Examples:"
echo " $0 # Interactive mode with list view"
echo " $0 -t # Interactive mode with table view"
echo " $0 -d # Disable HT immediately"
echo " $0 -e -t # Enable HT and show table view"
exit 0
;;
*)
echo "Unknown option: $1"
echo "Use -h or --help for usage information"
exit 1
;;
esac
done
function cacheTopology() {
# Cache topology information - temporarily enable offline threads to read topology
# Save original state
declare -A original_state
for CPU in $(printf '%s\n' /sys/devices/system/cpu/cpu[0-9]* | sort -V); do
CPUID=`basename $CPU | cut -b4-`
# Save original state
if [ -e $CPU/online ]; then
original_state[$CPUID]=$(cat $CPU/online 2>/dev/null || echo "1")
# Temporarily bring thread online to read topology
[ -w $CPU/online ] && echo "1" > $CPU/online 2>/dev/null
else
original_state[$CPUID]=1 # Thread 0 is always online
fi
done
# Small delay to ensure threads are fully online
sleep 0.1
# Read topology from all threads
for CPU in $(printf '%s\n' /sys/devices/system/cpu/cpu[0-9]* | sort -V); do
CPUID=`basename $CPU | cut -b4-`
# Cache sibling list if available
if [ -e $CPU/topology/thread_siblings_list ]; then
CACHED_SIBLINGS[$CPUID]=`cat $CPU/topology/thread_siblings_list`
# Parse and build sibling map
SIBLINGS="${CACHED_SIBLINGS[$CPUID]}"
PRIMARY=$(echo "$SIBLINGS" | cut -d',' -f1 | cut -d'-' -f1)
SECONDARY=$(echo "$SIBLINGS" | cut -d',' -f2 | cut -d'-' -f2)
if [ "$PRIMARY" != "$SECONDARY" ] && [ -n "$SECONDARY" ]; then
# Map both directions
CACHED_SIBLING_MAP[$PRIMARY]=$SECONDARY
CACHED_SIBLING_MAP[$SECONDARY]=$PRIMARY
# Mark which is primary (first in siblings list)
CACHED_PRIMARY[$PRIMARY]=1
CACHED_PRIMARY[$SECONDARY]=0
fi
fi
done
# Restore original state
for CPU in $(printf '%s\n' /sys/devices/system/cpu/cpu[0-9]* | sort -V); do
CPUID=`basename $CPU | cut -b4-`
ORIG_STATE="${original_state[$CPUID]}"
if [ -n "$ORIG_STATE" ] && [ -w $CPU/online ]; then
echo "$ORIG_STATE" > $CPU/online 2>/dev/null
fi
done
}
function toggleHyperThreading() {
# Only show line-by-line output if not in table view
local SHOW_OUTPUT=1
if [ "$TABLE_VIEW" -eq "1" ]; then
SHOW_OUTPUT=0
fi
for CPU in $(printf '%s\n' /sys/devices/system/cpu/cpu[0-9]* | sort -V); do
CPUID=`basename $CPU | cut -b4-`
[ "$SHOW_OUTPUT" -eq "1" ] && echo -en "${BOLD}Thread:${RESET} $CPUID\t"
[ -w $CPU/online ] && echo "1" > $CPU/online
THREAD1=`cat $CPU/topology/thread_siblings_list | cut -f1 -d,`
if [ $CPUID = $THREAD1 ]; then
[ "$SHOW_OUTPUT" -eq "1" ] && echo -e "${GREEN}-> online (primary)${RESET}"
[ -w $CPU/online ] && echo "1" > $CPU/online
else
if [ "$HYPERTHREADING" -eq "0" ]; then
[ "$SHOW_OUTPUT" -eq "1" ] && echo -e "${RED}-> offline (HT sibling)${RESET}"
else
[ "$SHOW_OUTPUT" -eq "1" ] && echo -e "${ORANGE}-> online (HT sibling)${RESET}"
fi
[ -w $CPU/online ] && echo "$HYPERTHREADING" > $CPU/online
fi
done
}
function enabled() {
echo -e "${GREEN}${BOLD}Enabling Hyperthreading (bringing HT sibling threads online)${RESET}\n"
HYPERTHREADING=1
toggleHyperThreading
# Show result in appropriate format
if [ "$TABLE_VIEW" -eq "1" ]; then
echo ""
showCurrentStateTable
fi
}
function disabled() {
echo -e "${RED}${BOLD}Disabling Hyperthreading (taking HT sibling threads offline)${RESET}\n"
HYPERTHREADING=0
toggleHyperThreading
# Show result in appropriate format
if [ "$TABLE_VIEW" -eq "1" ]; then
echo ""
showCurrentStateTable
fi
}
function showCurrentState() {
echo -e "${BOLD}Current Thread Status:${RESET}\n"
for CPU in $(printf '%s\n' /sys/devices/system/cpu/cpu[0-9]* | sort -V); do
CPUID=`basename $CPU | cut -b4-`
echo -en "${BOLD}Thread:${RESET} $CPUID\t"
# Check if thread is online
if [ -e $CPU/online ]; then
ONLINE_STATUS=$(cat $CPU/online)
else
# Thread 0 doesn't have online file, it's always online
ONLINE_STATUS=1
fi
# Check if thread is offline - if so, topology files won't exist
if [ "$ONLINE_STATUS" -eq "0" ]; then
echo -e "${RED}-> offline (HT sibling)${RESET}"
continue
fi
# For online threads, determine if it's a primary or secondary thread
if [ -e $CPU/topology/thread_siblings_list ]; then
THREAD1=`cat $CPU/topology/thread_siblings_list | cut -f1 -d,`
if [ $CPUID = $THREAD1 ]; then
# Primary thread
echo -e "${GREEN}-> online (primary)${RESET}"
else
# Secondary thread (HT sibling)
echo -e "${ORANGE}-> online (HT sibling)${RESET}"
fi
else
# Topology file doesn't exist, just show online status
echo -e "${GREEN}-> online${RESET}"
fi
done
echo ""
}
function showCurrentStateTable() {
# Get current status for all threads (topology is cached globally)
declare -A cpu_status
declare -A processed
# Get current online/offline status for all threads
for CPU in $(printf '%s\n' /sys/devices/system/cpu/cpu[0-9]* | sort -V); do
CPUID=`basename $CPU | cut -b4-`
# Get online status
if [ -e $CPU/online ]; then
cpu_status[$CPUID]=$(cat $CPU/online)
else
cpu_status[$CPUID]=1 # Thread 0 is always online
fi
done
# Print table header
echo -e "${BOLD}┌───────────────────────┬───────────────────────┐${RESET}"
echo -e "${BOLD}│ Primary Thread │ HT Sibling │${RESET}"
echo -e "${BOLD}├───────────────────────┼───────────────────────┤${RESET}"
# Display all threads in pairs using cached topology
for CPU in $(printf '%s\n' /sys/devices/system/cpu/cpu[0-9]* | sort -V); do
CPUID=`basename $CPU | cut -b4-`
# Skip if already processed
[ "${processed[$CPUID]}" = "1" ] && continue
# Check if this thread has a sibling (use cached data)
SIBLING="${CACHED_SIBLING_MAP[$CPUID]}"
if [ -n "$SIBLING" ]; then
# Mark both as processed
processed[$CPUID]=1
processed[$SIBLING]=1
# Get status for both threads
STATUS1="${cpu_status[$CPUID]}"
STATUS2="${cpu_status[$SIBLING]}"
# Determine display order: online thread goes in Primary column
# If both online or both offline, use cached primary designation
if [ "$STATUS1" -eq "1" ] && [ "$STATUS2" -eq "0" ]; then
# CPUID is online, SIBLING is offline - CPUID is primary
PRIMARY=$CPUID
SECONDARY=$SIBLING
elif [ "$STATUS1" -eq "0" ] && [ "$STATUS2" -eq "1" ]; then
# SIBLING is online, CPUID is offline - SIBLING is primary
PRIMARY=$SIBLING
SECONDARY=$CPUID
else
# Both same status - use cached topology
if [ "${CACHED_PRIMARY[$CPUID]}" = "1" ]; then
PRIMARY=$CPUID
SECONDARY=$SIBLING
else
PRIMARY=$SIBLING
SECONDARY=$CPUID
fi
fi
# Get status for primary (should be online or both same status)
PRIMARY_STATUS="${cpu_status[$PRIMARY]}"
if [ "$PRIMARY_STATUS" -eq "1" ]; then
PRIMARY_COLOR="${GREEN}"
PRIMARY_SYMBOL="✓"
else
PRIMARY_COLOR="${RED}"
PRIMARY_SYMBOL="✗"
fi
# Build display strings
PRIMARY_TEXT=$(printf "Thread %-2s %s" "$PRIMARY" "$PRIMARY_SYMBOL")
# Get status for secondary (HT sibling)
SECONDARY_STATUS="${cpu_status[$SECONDARY]}"
if [ "$SECONDARY_STATUS" -eq "1" ]; then
HT_COLOR="${ORANGE}"
HT_SYMBOL="✓"
else
HT_COLOR="${RED}"
HT_SYMBOL="✗"
fi
HT_TEXT=$(printf "Thread %-2s %s" "$SECONDARY" "$HT_SYMBOL")
# Print row with proper alignment
printf "│ ${PRIMARY_COLOR}%-16s${RESET} \t│ ${HT_COLOR}%-16s${RESET} \t│\n" \
"$PRIMARY_TEXT" "$HT_TEXT"
else
# Single-threaded core (no HT sibling)
processed[$CPUID]=1
STATUS="${cpu_status[$CPUID]}"
if [ "$STATUS" -eq "1" ]; then
COLOR="${GREEN}"
SYMBOL="✓"
else
COLOR="${RED}"
SYMBOL="✗"
fi
THREAD_TEXT=$(printf "Thread %-2s %s" "$CPUID" "$SYMBOL")
printf "│ ${COLOR}%-16s${RESET} \t│ %-16s \t│\n" \
"$THREAD_TEXT" "N/A"
fi
done
echo -e "${BOLD}└───────────────────────┴───────────────────────┘${RESET}"
echo ""
echo -e "Legend: ${GREEN}✓${RESET} = Online (Primary) ${ORANGE}✓${RESET} = Online (HT) ${RED}✗${RESET} = Offline"
echo ""
}
#
ONLINE=$(cat /sys/devices/system/cpu/online)
OFFLINE=$(cat /sys/devices/system/cpu/offline)
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 1
fi
# Cache topology information while all threads are online
cacheTopology
# If auto mode is enabled, toggle and exit
if [ "$AUTO_MODE" -eq "1" ]; then
if [ "$HYPERTHREADING" -eq "1" ]; then
enabled
else
disabled
fi
# For list view, show final summary
if [ "$TABLE_VIEW" -eq "0" ]; then
echo ""
echo "---------------------------------------------------"
ONLINE=$(cat /sys/devices/system/cpu/online)
OFFLINE=$(cat /sys/devices/system/cpu/offline)
echo -en "Threads online: $ONLINE\t Threads offline: $OFFLINE\n"
echo "---------------------------------------------------"
fi
exit 0
fi
# Interactive mode - show current state first
if [ "$TABLE_VIEW" -eq "1" ]; then
showCurrentStateTable
else
echo "---------------------------------------------------"
echo -en "Threads online: $ONLINE\t Threads offline: $OFFLINE\n"
echo "---------------------------------------------------"
showCurrentState
echo "---------------------------------------------------"
fi
# Interactive prompt
while true; do
read -p "Type in e to enable or d to disable hyperthreading or q to quit [e/d/q] ?" ed
case $ed in
[Ee]* ) enabled; break;;
[Dd]* ) disabled;exit;;
[Qq]* ) exit;;
* ) echo "Please answer e for enable or d for disable hyperthreading.";;
esac
done
@gabrielctn
Copy link

Nice, thank you for this usefull snippet ! 👍

@samueljon
Copy link
Author

Nice to know that you found it useful @gabrielctn

@AntonBikineev
Copy link

Thanks, indeed very useful!

@ha3ant
Copy link

ha3ant commented Oct 25, 2020

hi sir, I'm beginner in Linux, how can I use this bash file?

@samueljon
Copy link
Author

@ha3ant I would click the "raw" button at the top of the script and copy the contents of the script. Then on the machine where you will be running the script open a file editor where you will paste the content and save as f.ex togglHt.sh. Then you would make the script executable by issuing following command in a terminal chmod +x toggleHT.sh. After that you should be able to run it from the directory where you saved it f.ex. ./toggleHT.sh

@zhongshanxu
Copy link

Great!

@nevil02
Copy link

nevil02 commented Feb 28, 2022

this is givinig me prermission denied:
bash: /sys/devices/system/cpu/cpu6/online: Permission denied
for all cpus

@samueljon
Copy link
Author

@nevil02 you must run this script as root. I have updated the script to check if the user running the script is root, otherwise printing "The script must be run as root". You could do sudo ./toogleHT.sh or become root to execute.

@nevil02
Copy link

nevil02 commented Feb 28, 2022

it is giving me following message
sudo: ./hyperthreading-on-off.sh: command not foun

@samueljon
Copy link
Author

@nevil02 did you create the script as hyperthreading-on-off.sh and have you made it executable by doing chmod +x hyperthreading-on-off.sh before running it ?

@nevil02
Copy link

nevil02 commented Feb 28, 2022

done, Thank you

@samueljon
Copy link
Author

@nevil02 my pleasure 👍

@LePingKYXK
Copy link

Hi, thank you for sharing this code.
I was wondering that if my CPU has 16 cores, should I change the code cpu[0-9] in the 6th line into cpu[0-15]?

@LePingKYXK
Copy link

@ha3ant I would click the "raw" button at the top of the script and copy the contents of the script. Then on the machine where you will be running the script open a file editor where you will paste the content and save as f.ex togglHt.sh. Then you would make the script executable by issuing following command in a terminal chmod +x toggleHT.sh. After that you should be able to run it from the directory where you saved it f.ex. ./toggleHT.sh

Hi, I am not sure what's the meaning of "save as f.ex toggIHt.sh".
The coed is a bash code, and it would be as toggIHt.sh. What is the f.ex mean?

@samueljon
Copy link
Author

@LePingKYXK i do not think you need to change code in line 6. I did test this with more than ten cpu's. F.ex means for example.

@LePingKYXK
Copy link

@LePingKYXK i do not think you need to change code in line 6. I did test this with more than ten cpu's. F.ex means for example.

Thanks a lot. It works well.

@kerwinyin
Copy link

prefect,thanks

@blazer502
Copy link

Perfect, thanks a lot.

@RohanKapurDEV
Copy link

hey this actually works, nice!

@sm5hua
Copy link

sm5hua commented Aug 10, 2024

Works like a charm on my old Slackare 14.2 with a i7-4810mq - Thanks!

@rorar
Copy link

rorar commented Oct 16, 2024

@samueljon Would it be possibel for you to add a few checks?

  1. Check if CPU is HT capable
  2. Check if HT is enabled or disabled
  3. Check for availabe cores and threads per cores

Edit: Did some work here...
https://gist.github.com/rorar/cebde935cf4dfa6389df96c4df79ce38
Not perfect, still need polishing (colored text output, disable selected cores,...) . Do you want to give it a try?

@samueljon
Copy link
Author

@samueljon Would it be possibel for you to add a few checks?

  1. Check if CPU is HT capable
  2. Check if HT is enabled or disabled
  3. Check for availabe cores and threads per cores

Edit: Did some work here... https://gist.github.com/rorar/cebde935cf4dfa6389df96c4df79ce38 Not perfect, still need polishing (colored text output, disable selected cores,...) . Do you want to give it a try?

Nice I will have a look when I can @rorar . Thanks for the inspiration in your implementation.

@antermin
Copy link

antermin commented Feb 8, 2026

Hello, I noticed that the script does not output the CPUs in correct order.

Actual output:

---------------------------------------------------
CPU's online: 0-11       CPU's offline: 
---------------------------------------------------
Type in e to enable or d disable hyperThreading or q to quit [e/d/q] ?d
Disabling HyperThreading
CPU: 0  -> enable
CPU: 1  -> enable
CPU: 10 -> disabled
CPU: 11 -> disabled
CPU: 2  -> enable
CPU: 3  -> enable
CPU: 4  -> enable
CPU: 5  -> enable
CPU: 6  -> disabled
CPU: 7  -> disabled
CPU: 8  -> disabled
CPU: 9  -> disabled

Expected output:

---------------------------------------------------
CPU's online: 0-11       CPU's offline: 
---------------------------------------------------
Type in e to enable or d disable hyperThreading or q to quit [e/d/q] ?d
Disabling HyperThreading
CPU: 0  -> enable
CPU: 1  -> enable
CPU: 2  -> enable
CPU: 3  -> enable
CPU: 4  -> enable
CPU: 5  -> enable
CPU: 6  -> disabled
CPU: 7  -> disabled
CPU: 8  -> disabled
CPU: 9  -> disabled
CPU: 10 -> disabled
CPU: 11 -> disabled

@samueljon
Copy link
Author

Thanks for reporting this @antermin and I have mades some improvements and also taken the considerations from @rorar into account. Here is the changelog:

Display Enhancements

  • Add table view mode (-t/--table flag) showing thread pairs grouped by physical core
  • Use Unicode box-drawing characters for clean table borders
  • Add color-coded output:
    • Green: online primary threads
    • Orange: online HT sibling threads
    • Red: offline threads
  • Bold formatting for labels and headers

Bug Fixes

  • Fix CPU ordering to use numeric sort instead of lexicographic (0,1,2...10,11 not 0,1,10,11)
  • Handle CPU 0 permission errors (boot CPU cannot be taken offline)
  • Check file writability before attempting to modify /sys/devices/system/cpu/*/online

Functionality Improvements

  • Add non-interactive mode with -e/--enable and -d/--disable flags
  • Cache topology information at startup to handle offline threads correctly
  • Smart display logic: online threads are always shown in the Primary column when HT is disabled
  • Preserve thread pairing information even when siblings are offline
  • Temporarily enable offline threads during cache to read topology files

Terminology Updates

  • Use "Thread" instead of "CPU" for logical processors
  • Use "Physical Core" for hardware cores
  • Clarify "Primary Thread" vs "HT Sibling" throughout
  • Update all messages and labels for consistency

Architecture

  • Global topology cache (CACHED_SIBLINGS, CACHED_SIBLING_MAP, CACHED_PRIMARY)
  • Separate functions for list and table views
  • cacheTopology() function to preserve sibling relationships
  • Conditional output in toggleHyperThreading() based on view mode

Usage

  • Interactive mode: ./toggleHT.sh [-t]
  • Direct disable: ./toggleHT.sh -d [-t]
  • Direct enable: ./toggleHT.sh -e [-t]
  • Help: ./toggleHT.sh -h

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment