patternshellMinor
zsh system status script
Viewed 0 times
scriptsystemzshstatus
Problem
The following script is being used to generate the status line in wmii. I'm curious if there are faster/more efficient ways to find the various info I'm grabbing. I'm also a relative newbie when it comes to zsh (and shell scripting in general) so I'd also suspect that there are better ways to process some of the data.
#!/bin/zsh
cpu_freq=$(grep "cpu MHz" /proc/cpuinfo | sed 's/[\t ]*//g; s/cpuMHz://g')
cpu0=$(echo "scale=2;" `echo $cpu_freq | head -n 1 | tail -n 1` / 1000 | bc)
cpu1=$(echo "scale=2;" `echo $cpu_freq | head -n 2 | tail -n 1` / 1000 | bc)
cpu2=$(echo "scale=2;" `echo $cpu_freq | head -n 3 | tail -n 1` / 1000 | bc)
cpu3=$(echo "scale=2;" `echo $cpu_freq | head -n 4 | tail -n 1` / 1000 | bc)
stat=$(mpstat | tail -n 1 | tr -s ' ')
usr=$(echo $stat | cut -d ' ' -f 4)
nice=$(echo $stat | cut -d ' ' -f 5)
sys=$(echo $stat | cut -d ' ' -f 6)
cpu=$(echo $usr + $nice + $sys | bc)
memline=$(free | head -n 2 | tail -n 1 | tr -s ' ')
cached=$(echo $memline | cut -d ' ' -f 7)
free=$(echo $memline | cut -d ' ' -f 4)
cachedfree=$(echo $cached + $free | bc)
mem=$(echo "scale=3;" $cachedfree / 1000000 | bc)
network=$(nmcli nm | sed 's/ */\;/g' | cut -d \; -f 2 | tail -n 1)
tun0=$(ifconfig tun0 2>/dev/null)
vpn=$(if [[ -n $tun0 ]]; then; echo "(vpn:" $(cat /tmp/current-vpn)")"; else; echo ""; fi)
battery=$(acpi -b | sed 's/Battery 0: //; s/ until charged//; s/ remaining//; s/Charging/C/; s/Discharging/D/; s/Full, //; s/Unknown, //')
load=$(uptime | sed 's/.*://; s/,//g')
date=$(date +%a\ %b\ %d\ %H:%M)
echo -n $vpn $network '||' $mem GB '||' $cpu% '('$cpu0 $cpu1 $cpu2 $cpu3') ||' $load '||' $date '||' $batterySolution
Extracting a column
It's a lot easier to extract columns from text using awk.
Instead of this:
This is shorter, and uses a single awk process instead of
Extracting a line
This is a really awkward method to extract the 4th line:
This is simpler and better:
Using arrays
Instead of getting the values of
Explanation:
From this array, you can extract the individual CPU values
Next steps
I don't want to spoil all the fun for you :-)
Following the techniques above,
you should be able to extract the other values more efficiently (using fewer processes) in a similar fashion.
It's a lot easier to extract columns from text using awk.
Instead of this:
grep "cpu MHz" /proc/cpuinfo | sed 's/[\t ]*//g; s/cpuMHz://g'This is shorter, and uses a single awk process instead of
grep + sed:awk '/cpu MHz/ {print $4}' /proc/cpuinfoExtracting a line
This is a really awkward method to extract the 4th line:
echo $cpu_freq | head -n 4 | tail -n 1This is simpler and better:
sed -ne 4p <<< "$cpu_freq"Using arrays
Instead of getting the values of
cpu0..cpu3 one by one by running separate command(s) for each, you can get it in one go:cpus=($({ echo scale=2; awk '/cpu MHz/ {print $4 " / 1000"}' /proc/cpuinfo; } | bc))Explanation:
- The
awkcommand appends the" / 1000"to the CPU frequency, so it's ready for piping tobc
- Pipe all lines (commands) to
bcat once, and get all the output at once
- Group the
echo scale=2and theawkforbcby enclosing in{ ...; }
- Store the output of
bcin an array
From this array, you can extract the individual CPU values
cpu0=${cpus[0]}
cpu1=${cpus[1]}
cpu2=${cpus[2]}
cpu3=${cpus[3]}Next steps
I don't want to spoil all the fun for you :-)
Following the techniques above,
you should be able to extract the other values more efficiently (using fewer processes) in a similar fashion.
Code Snippets
grep "cpu MHz" /proc/cpuinfo | sed 's/[\t ]*//g; s/cpuMHz://g'awk '/cpu MHz/ {print $4}' /proc/cpuinfoecho $cpu_freq | head -n 4 | tail -n 1sed -ne 4p <<< "$cpu_freq"cpus=($({ echo scale=2; awk '/cpu MHz/ {print $4 " / 1000"}' /proc/cpuinfo; } | bc))Context
StackExchange Code Review Q#32008, answer score: 2
Revisions (0)
No revisions yet.