(2014-03-31) Viewing Resource Usage in Bash

So I stumbled across some fairly useful commands recently and decided to expand things out a bit.

ps awwfux | grep --color=none $USER | less -S
This command will print the processes running as the current user (and the login process for that user), and display them in a tree structure. The less command allows you to scroll both horizontally and veritically.
ps -eo pcpu | egrep -v "0.0|CPU" | awk '{sum+=$1}END{print sum}'
This returns the current CPU usage (as a percentage); it doesn't nessecarily have much of a use on it's own, but with a little bit of work you could do something like this:
#!/bin/bash

cpu_usage() {
        p=$( ps -eo pcpu | egrep -v "0.0|CPU" | awk '{sum+=$1}END{print sum}' )
        p=$( echo "${p} * 10" | bc )
        p=$(( ${p:0:2} / 10 / 2 ))
        i=0
        printf "[" 
        while [[ ${i} -le 50 ]]; do
                [[ ${i} -le ${p} ]] && printf "#" || printf "-" 
                (( i++ ))
        done
        printf "]" 
}

main() {
        cpu_usage
        sleep 1
        for (( i=0; i <= 102; i++ )); do
                printf "\b"
        done
        main
}

main
Which will display a nice meter:
[#####----------------------------------------------]
Similarly, with a bit of effort you can do the same for memory usage. Starting off with:
t=$( echo $( cat /proc/meminfo | grep "MemTotal" | awk '{print $2}' ) / 1024 | bc )
f=$( echo $( cat /proc/meminfo | grep "MemFree" | awk '{print $2}') / 1024 | bc )
u=$(( $t - $f ))
p=$( echo "scale=2
${u} / ${t}" | bc | cut -d "." -f 2 )
echo ${p}
Which outputs a similar result to the initial CPU usage command. But can just as easily be converted into a bar like this:
#!/bin/bash

mem_usage() {
        t=$( echo $( cat /proc/meminfo | grep "MemTotal" | awk '{print $2}' ) / 1024 | bc )
        f=$( echo $( cat /proc/meminfo | grep "MemFree" | awk '{print $2}') / 1024 | bc )
        u=$(( $t - $f ))
        p=$( echo "scale=2; ${u} / ${t}" | bc | cut -d "." -f 2 )
        i=0
        printf "["
        while [[ ${i} -le 50 ]]; do
                [[ ${i} -le $(( ${p} / 2 )) ]] && printf "#" || printf "-"
                (( i++ ))
        done
        printf "]"
}

main() {
        mem_usage
        sleep 1
        for (( i=0; i <= 102; i++ )); do
                printf "\b"
        done
        main
}

main
With the familiar bar output:
[#########------------------------------------------]
As you can probably tell, the code is almost identical, the main difference is what generates ${p}. Also, it's really pretty simple to change the size of the bars, you just have to change the while loop to a lower number (this is the number of characters the bar will take up) and divide ${p} by 100 divided by whatever the value of ${i} will reach. EDIT: So, I had a quick think, and it's again trivial to work the percentage out for disk usage as well. Fortunately, you don't even need to do much in the way of calculations if you already have "df"; you can simply run:
df -h --output=source,pcent | grep "/dev/" | awk '{sum+=$2}END{print sum}'
You don't need the "source" output field, but it makes it easier to distinguish physical drives versus RAM disks etc. Again, can be made into a fany bar with minimal effort:
disk_usage() {
        p=$( df -h --output=source,pcent | grep "/dev/" | awk '{sum+=$2}END{print sum}' )
        i=0 
        printf "[" 
        while [[ ${i} -le 50 ]]; do
                [[ ${i} -le $(( ${p} / 2 )) ]] && printf "#" || printf "-" 
                (( i++ ))
        done
        printf "]" 
}

main() {
        disk_usage
        sleep 1
        for (( i=0; i <= 102; i++ )); do
                printf "\b"
        done
        main
}

main
Then, if you wanted all three in one, you could easily put the meters in like:
main() {
        cpu_usage
        printf "\t"
        mem_usage
        printf "\t"
        disk_usage
        sleep 1
        for (( i=0; i <= 312; i++ )); do
                printf "\b"
        done
        main
}
Though using the "\b" (backspace) character is very useful in keeping the terminal clean, it is limited when it comes to line breaks (in that it doens't work), so using "clear" may be a better option if you were building some kind of GUI. Alternatively, you could plug the numbers into dialog / xdialog really easily. Something like this would work (although doesn't provide any options and you need to * 10 / 10 to round the number):
dialog --gauge test 10 30 $(( $( ps -eo pcpu | egrep -v "0.0|CPU" | awk '{sum+=$1}END{print sum}' ) * 10 / 10 ))
As usual, this stuff has been added to bashlib -- the latest copy can be obtained from git ( https://github.com/edgleyUK/bashlib )