I have written a bash script file designed to work with the cpufrequtils package and the programs cpufreq-info (for reading CPU speed info) and cpufreq-set (to set CPU speed governor and frequency). This is my first attempt at writing a bash shell to interface with these two packages. After creating a blog on how to use YaST to set your CPU speed with yast-power-management you can read about here: YaST Power Management - Control Your CPU Energy Usage How To & FAQ - Blogs - openSUSE Forums, several forum users indicated they used the cpufreq utilities instead. So, I decided to see if any sort of value added bash script could be put together to work with this program set. Changes made to your CPU speed only last until your reboot your computer, but you may find the information and function it provides to be useful.
To use the bash script file cfu, you need to copy and past the following text from the code block into a text editor like kwrite:
#!/bin/bash
#: Title : cfu - CPU Frequency Utility
#: Date Created: Wed Jun 22 17:03:27 CDT 2011
#: Last Edit : Fri Jul 08 21:53:00 CDT 2011
#: Author : J. McDaniel
#: Version : 1.00
#: Description : display and set CPU Frequency
#: Options : none
#: Notes : cfu will ask to install cpufrequtils if not installed
TITLE="CPU Frequency Utility - Version 1.00"
#
# Written for the openSUSE forums on Friday July 8, 2011
#
#
# Copy and Paste the text of this script into a text editor and save
# it as the file cfu in the /home area bin folder
# example is: /home/username/bin, also known as ~/bin
# This script must be marked executable to be used. Please
# run the following Terminal command: chmod +x ~/bin/cfu
# To use cfu, open a terminal session and type in: cfu
#
declare -a governs
declare -a spdsteps
#
# Display GPL Standard Statement
#
function show_gpl {
tput clear
echo "CFU is designed to run the cpufrequtils package in openSUSE."
echo "Copyright (C) 2011 by James D. McDaniel, jmcdaniel3@austin.rr.com"
echo
echo "This program is free software; you can redistribute it and/or modify"
echo "it under the terms of the GNU General Public License as published by"
echo "the Free Software Foundation; either version 2 of the License, or"
echo "(at your option) any later version."
echo
echo "This program is distributed in the hope that it will be useful,"
echo "but WITHOUT ANY WARRANTY; without even the implied warranty of"
echo "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"
echo "GNU General Public License for more details."
echo
echo "You should have received a copy of the GNU General Public License"
echo "along with this program; if not, write to the Free Software"
echo "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA"
echo
}
#
# Find the brand/model of the CPU in this PC
#
if -f /proc/cpuinfo ]; then
cpuname=$(grep -m 1 "model name" /proc/cpuinfo | cut -d: -f2 | sed -e 's/^ *//' | sed -e 's/$//')
fi
# Remove Extra Spaces in $cpuname if they should exist
cpuname=$(echo "$cpuname" |awk '{$1=$1}1' OFS=" ")
#
# Find out number of CPU cores, Hyper-threading will double this number
#
Number_CPUS=$(grep -m 1 "cpu cores" /proc/cpuinfo | cut -d: -f2 | sed -e 's/^ *//' | sed -e 's/$//')
hyper=false
if $(cat /proc/cpuinfo) = *siblings* ]] ; then
hyperthreads=$(grep -m 1 "siblings" /proc/cpuinfo | cut -d: -f2 | sed -e 's/^ *//' | sed -e 's/$//')
if $((Number_CPUS)) -lt $((hyperthreads)) ] ; then
hyper=true
fi
fi
#
# Locate Substring by space seperator in a long string
#
function sub_string {
counter=$1
start=$2
num2=${#start}
while $(( counter )) -lt $(( num2 + 1 )) ] ; do
temp="${start:$(($counter)):1}"
if $temp != " " ]] ; then
let counter=counter+1
else
return ${counter}
fi
done
return ${counter}
}
#
# Load Substrings into an array ${governs[0]}
# Uses user Function called sub_string
#
function savegovern {
savgov=$1
string=$savgov; string="${string//^ ]/}"
let string=${#string}+1
place=0
glen=0
while place -lt string ]] ; do
let place=place+1
savlst=$((glen))
sub_string "$glen" "$savgov"
glen="$?"
governs$place]="${savgov:$((savlst)):$((glen-savlst))}"
let glen=glen+1
done
return ${place}
}
#
# Format RAW CPU Speed Display function
#
function form_speed {
spd=$1
num1=$(((spd) / 1000 ))
formed=$(printf "%'d GHz
" $num1)
formed=$(echo $formed | tr ',' '.')
}
#
# Display All Text in Color as requested
#
# syntax: print_color line col fgrd_color bgrd_color #lines "text"...
#
# 0: Black 1: Blue 2: Green 3: Cyan 4: Red 5: Magenta 6: Yellow 7: White
#
function print_color {
WIDTH=$(tput cols)
HEIGHT=$(tput lines)
line_os=0
if $(($WIDTH)) -le 80 ] ; then
col_os=0
else
col_os=$((($WIDTH - 80) / 2 ))
fi
s_line=${1}
s_col=${2}
fgrd=${3}
bgrd=${4}
maxnum=${5}
counter=0
while $(( counter )) -lt $(( maxnum )) ] ; do
tput cup $(( s_line + counter + line_os)) $(( s_col + col_os ))
tput bold
tput setf $(( fgrd ))
tput setb $(( bgrd ))
echo -n "${6}$(tput sgr0)"
let counter=counter+1
shift
done
}
#
# Display Main Menu function
#
function main_menu {
tput clear
print_color 2 0 7 2 1 " $TITLE "
l1="---------------------------------------------------------------------------"
l2=""
l3="---------------------------------------------------------------------------"
l4=" CPU Name: $cpuname"
if $hyper ; then
l5=" CPU Cores: $Number_CPUS with Hyper-Threading"
else
l5=" CPU Cores: $Number_CPUS"
fi
l6=" CPU Speed: $freq"
l7=" Speed Range: $lowest to $highest"
l8="---------------------------------------------------------------------------"
print_color 1 0 7 0 8 "$l1" "$l2" "$l3" "$l4" "$l5" "$l6" "$l7" "$l8"
l1=" Governor: $policy"
l2=" Your $totopt Options: $govern"
l3="---------------------------------------------------------------------------"
l4=""
l5="---------------------------------------------------------------------------"
print_color 9 0 7 0 5 "$l1" "$l2" "$l3" "$l4" "$l5"
l1=" Please make your selection, S=Set Governor or Q=Quit (S/Q): "
print_color 12 7 6 1 1 "$l1"
}
#
# Set Speed Governor with cpufreq-set for ALL CPU's
#
function govern_set {
countII=0
while countII -lt Number_CPUS+Number_CPUS ]] ; do
sudo cpufreq-set -c $((countII)) -g "$1"
let countII=countII+1
done
sleep 1
}
#
# Set CPU speed when governor=userspace with cpufreq-set for ALL CPU's
#
function setfreq {
freqset="${spdsteps$1]}"
freqlen=${#freqset}
let freqlen=freqlen-4
freqset=${freqset:0:$((freqlen))}
countII=0
while countII -lt Number_CPUS+Number_CPUS ]] ; do
sudo cpufreq-set -c $((countII)) -f $freqset"GHz"
let countII=countII+1
done
sleep 1
}
#
# Determine if the package cpufrequtils is installed
#
which cpufreq-info > /dev/null
Exit_Code=$?
if $(( Exit_Code )) -ge 1 ] ; then
tput clear
echo "The CPU frequency Utilities Package is not installed!"
echo
echo -n "Would you like to install the cpufrequtils package(y/N)?"
read CHOICE
if $CHOICE == [Yy] ]] ; then
sudo zypper install cpufrequtils
else
exit 1
fi
fi
#
# Main Program Starts Here *****************************************
#
gui=true
while $gui ; do
#
# Find Active CPU Speed - cpufreq-info -f
#
freq=$(cpufreq-info -f)
form_speed "$freq"
freq=$formed
#
# Find Lowest Speed / Highest Speed / CPU Speed Policy - cpufreq-info -p
#
rang=$(cpufreq-info -p)
savegovern "$rang"
#
# Set Lowest CPU Speed
#
lowest="${governs[1]}"
form_speed "$lowest"
lowest=$formed
#
# Set Highest CPU Speed
#
highest="${governs[2]}"
form_speed "$highest"
highest=$formed
#
# Set CPU Speed Policy
#
policy="${governs[3]}"
policy=$(echo $policy | tr '[a-z]' '[A-Z]')
#
# Determine userspace speeds which can be used and load into array
#
# Locate Just speed Listing Sub-string for CPU 0
cpuspd=$(cpufreq-info -c 0)
cpuspd=${cpuspd%" available cpufreq governors"*}
cpuspd=${cpuspd##*" available frequency steps: "}
# Breakup Speeds found into an Array
# Change all spaces to Underscore
# Then Change all commas to spaces
cpuspd=$(echo $cpuspd | tr ' ' '_')
cpuspd=$(echo $cpuspd | tr ',' ' ')
savegovern "$cpuspd"
totspd="$?"
# Move array values from governs to spdsteps
# Change all Underscores to spaces
# Trim off excess spaces
counter=0
while counter -lt totspd ]] ; do
let counter=counter+1
spdsteps$counter]=$( echo ${governs$counter]} | tr '_' ' ')
tmpspd=${spdsteps$counter]}
if "${tmpspd:0:1}" == " " ] ; then
tmpspd="${tmpspd:1:${#tmpspd}-1}"
spdsteps$counter]=$tmpspd
fi
done
# Find and remove adjacent duplicate CPU speeds
offset=0
counter=0
while counter -lt totspd ]] ; do
let counter=counter+1
if counter != totspd ]] ; then
if "${spdsteps$counter]}" == "${spdsteps$counter+1]}" ] ; then
let offset=offset+1
fi
fi
spdsteps$counter]=${spdsteps$counter+$offset]}
done
let totspd=totspd-offset
#
# Policy Selections cpufreq-info -g
#
govern=$(cpufreq-info -g)
savegovern "$govern"
totopt="$?"
govern=$(echo $govern | tr '[a-z]' '[A-Z]')
govern=$(echo $govern | tr ' ' ',')
#
# Show Main Menu and request user input
#
main_menu
read CHOICE
#
# CPU Speed Governor Selection
#
if $CHOICE == [Ss] ]] ; then
tput clear
echo $TITLE
echo
echo "CPU Governor Speed Selection Menu"
echo
echo "CONSERVATIVE - Similar to ondemand, but more conservative "
echo "(clock speed changes are more graceful)."
echo "USERSPACE - Manually configured clock speeds by user."
echo "POWERSAVE - Runs the CPU at minimum speed."
echo "ONDEMAND - Dynamically increases/decreases the CPU(s)"
echo "clock speed based on system load."
echo "PERFORMANCE - Runs the CPU(s) at maximum clock speed."
echo
echo "The Active Governor is: $policy"
echo
counter=0
while counter -lt totopt ]] ; do
let counter=counter+1
echo "$counter) ${governs$counter]}"
done
echo
echo -n "Enter the Governor Number to use [1-$((totopt))] (q=Quit):"
read CHOICE
if $CHOICE =~ ^[0-9]+$ ]] ; then
if $CHOICE -le $counter ]] && $CHOICE -gt 0 ]]; then
govern_set "${governs$CHOICE]}"
#
# CPU Speed Selection when Governor is set to userspace
#
if "${governs$CHOICE]}" == "userspace" ] ; then
setfreq 1
tput clear
echo $TITLE
echo
echo "CPU USERSPACE Speed Selection Menu"
echo
counter=0
while counter -lt totspd ]] ; do
let counter=counter+1
echo "$counter) ${spdsteps$counter]}"
done
echo
echo "NOTE: Actual Speed can be one step above selected"
echo " due to fractional speed values not shown."
echo
echo -n "Enter the CPU Speed Number to use [1-$((totspd))]:"
read CHOICE
if $CHOICE =~ ^[0-9]+$ ]] ; then
if $CHOICE -le $counter ]] && $CHOICE -gt 0 ]]; then
setfreq "$CHOICE"
fi
fi
fi
fi
else
gui=false
fi
fi
if $CHOICE == [Qq] ]] ; then
gui=false
fi
done
show_gpl
exit 0
# End Of Script
Save the text as the file cfu in the /home area bin folder (example is: /home/username/bin, also known as ~/bin). This script must be marked executable to be used. Please run the following Terminal command:
chmod +x ~/bin/cfu
To use cfu, open a terminal session and type in:
cfu
If the cpufrequtils package is not installed, you will be prompted to install it. In order to change your governor or CPU speed, you must supply the root user password. Same goes for installing the cpufrequtils package if it is missing. As always, I would love to hear about any comments or problems you might have using cfu.
Thank You,