Shell Scripting to check System Performance
Last Updated :
23 Sep, 2022
Prerequisites: Bash Scripting, Shell Function Library
We will build a bash script to check :
- memory utilization
- CPU utilisation
- disk utilisation
And analyze the report and print messages or error warnings accordingly.
Creating Shell Script
The name of the script will be sysperform.sh. Make it an executable file.
$ touch sysperform.sh
$ chmod +x sysperform.sh
Step 1: Handling Argument Errors
$ ./sysperform.sh <args> # invalid syntax (the script doesn’t take any argument)
$ ./sysperform.sh # correct syntax
Open the file and add the following script :
#!/bin/bash
# if args have been specified, then
# show the correct syntax to the user
if [ $# -gt 0 ] ; then
echo "Invalid Syntax!"
echo "The valid syntax is ./$(basename $0)"
exit 1
fi
Step 2: Create Main Function
function main ()
{
memory_util
cpu_util
disk_util
}
main
The main function will call three functions as follows :
- memory_util will give information about Available memory, Free memory, Memory Used Percentage, etc., as well as reports on whether the memory is healthy or not.
- cpu_util will give information about CPU load and CPU usage and tell whether the CPU is performing well or not.
- disk_util will tell the disk used and disk available of the root partition and home partition.
Step 3: Create memory_util function
function memory_util ()
{
BUFFCACHE_MEM=$(free -m | awk '/Mem/ {print $6}')
FREE_MEM=$(free -m | awk '/Mem/ {print $4}')
YIELD_MEM=$(( $BUFFCACHE_MEM + $FREE_MEM ))
AVAILABLE_MEM=$(free -m | awk '/Mem/ {print $7}')
TOTAL_MEM=$(free -m | awk '/Mem/ {print $2}')
TOTAL_USED_MEM=$(( $TOTAL_MEM - $AVAILABLE_MEM ))
#Total memory usage is Total Memory - Available Memory
MEM_USAGE_PERCENT=$(bc <<<"scale=2; $TOTAL_USED_MEM * 100 / $TOTAL_MEM")
echo -e "........................................\nMEMORY UTILIZATION\n"
echo -e "Total Memory\t\t:$TOTAL_MEM MB"
echo -e "Available Memory\t:$AVAILABLE_MEM MB"
echo -e "Buffer+Cache Memory\t:$BUFFCACHE_MEM MB"
echo -e "Free Memory\t\t:$FREE_MEM MB"
echo -e "Memory Usage Percentage\t:$MEM_USAGE_PERCENT %"
#if available or (free+buffer+cache) is close to 0
#We will warn the user if it's below 100 MiB
if [ $AVAILABLE_MEM -lt 100 -o $YIELD_MEM -lt 100 ] ; then
echo "Available Memory or the free and buffer+cache Memory is too low!"
echo "Unhealthy Memory!"
#if kernel employed OOM Killer process
elif dmesg | grep oom-killer > /dev/null ; then
echo "System is critically low on memory!"
else
echo -e "\nMEMORY OK\n........................................"
fi
}
We will use the free -m command coupled with awk to filter our unnecessary details so as to view the free memory, available memory, buffer, and cached memory and finally calculate Memory used percentage.
We will use bc to handle Floating-point arithmetic operations in bash.
Some important facts :
- Linux tries to use unused RAM for disk caching to fasten up the operations. Do not be worried if free memory is close to 0.
- Free memory is basically unused wasted memory.
- Buffer and Cache memory contain metadata and actual contents from the disk so that the operations could be done quickly. Together we will call it YIELD_MEM(yield memory) since it can yield memory whenever a new process is started.
- Available memory is the actual memory that is available to the user.
- So actual memory used(which includes buffer & cache) = total memory – available memory
Memory is unhealthy if
- If available memory or the free+buffer+cache memory is too low.
- If kernel employs OOM(Out of Memory)-Killer process.
Step 4: Create cpu_util function
function cpu_util ()
{
#number of cpu cores
CORES=$(nproc)
#cpu load average of 15 minutes
LOAD_AVERAGE=$(uptime | awk '{print $10}')
LOAD_PERCENT=$(bc <<<"scale=0; $LOAD_AVERAGE * 100")
echo -e "........................................\nCPU UTILIZATION\n"
echo -e "Number of Cores\t:$CORES\n"
echo -e "Total CPU Load Average for the past 15 minutes\t:$LOAD_AVERAGE"
echo -e "CPU Load %\t\t\t\t\t:$LOAD_PERCENT"
echo -e "\nThe load average reading takes into account all the core(s) present in the system"
#if load average is equal to the number of cores, print warning
if [[ $(echo "if (${LOAD_AVERAGE} == ${CORES}) 1 else 0" | bc) -eq 1 ]] ; then
echo "Load average not ideal."
elif [[ $(echo "if (${LOAD_AVERAGE} > ${CORES}) 1 else 0" | bc) -eq 1 ]] ; then
echo "Critical! Load average is too high!"
else
echo -e "\nCPU LOAD OK"
fi
# capturing the second iteration of top and storing the CPU% id.
IDLE=$(top -b -n2 | awk '/Cpu/ {print $8}' | tail -1)
CPU_USAGE_PERCENT=$(bc <<<"scale=2; 100 - $IDLE/$CORES")
echo -e "\nCPU Usage %\t:$CPU_USAGE_PERCENT\n........................................"
}
We will use the bc command to evaluate the floating point operations in if-else statements.
- The healthy Load Average of each core is less than 1. top command displays the total load average of all the cores combined.
- Load Percentage = Lode Average * 100
- To calculate CPU Usage, we will divide the CPU time spent idle by the number of cores and subtract it by 100.
- CPU Usage % = 100 – (Idle time spent/number of cores)
- We will use the second iteration of the top command to view the correct idle time. -b helps to redirect output and -n2 refers to 2 iterations of the top command. tail -1 prints the last recorded idle time.
CPU is unhealthy if
- Load Average is greater than or equal to the number of cores
Step 5: Create disk_util function
function disk_util ()
{
ROOT_DISK_USED=$(df -h | grep -w '/' | awk '{print $5}')
ROOT_DISK_USED=$(printf %s "$ROOT_DISK_USED" | tr -d [="%"=])
ROOT_DISK_AVAIL=$(( 100 - $ROOT_DISK_USED ))
HOME_DISK_USED=$(df -h | grep -w '/home' | awk '{print $5}')
HOME_DISK_USED=$(printf %s "$HOME_DISK_USED" | tr -d [="%"=])
HOME_DISK_AVAIL=$(( 100 - $HOME_DISK_USED ))
echo -e "........................................\nDISK UTILIZATION\n"
echo -e "Root(/) Used\t\t:$ROOT_DISK_USED%"
echo -e "Root(/) Available\t:$ROOT_DISK_AVAIL%\n"
echo -e "Home(/home) Used\t:$HOME_DISK_USED%"
echo -e "Home(/home) Available\t:$HOME_DISK_AVAIL%"
#print warning if any of the disk is used above 95%
if [ $ROOT_DISK_USED -ge 95 -o $HOME_DISK_USED -ge 95 ] ; then
echo -e "\nDisk is almost full! Free up some space!"
else
echo -e "\nDISK OK"
fi
}
We will filter out unnecessary details from df -h with the help of grep and awk.
- We will check the used space and available space of root( / ) and home partition( /home ).
The disk is unhealthy if
- Disk space available is very less
Step 6: Putting together everything
#!/bin/bash
function memory_util ()
{
BUFFCACHE_MEM=$(free -m | awk '/Mem/ {print $6}')
FREE_MEM=$(free -m | awk '/Mem/ {print $4}')
YIELD_MEM=$(( $BUFFCACHE_MEM + $FREE_MEM ))
AVAILABLE_MEM=$(free -m | awk '/Mem/ {print $7}')
TOTAL_MEM=$(free -m | awk '/Mem/ {print $2}')
TOTAL_USED_MEM=$(( $TOTAL_MEM - $AVAILABLE_MEM ))
# Total memory usage is Total Memory - Available Memory
MEM_USAGE_PERCENT=$(bc <<<"scale=2; $TOTAL_USED_MEM * 100 / $TOTAL_MEM")
echo -e "........................................\nMEMORY UTILIZATION\n"
echo -e "Total Memory\t\t:$TOTAL_MEM MB"
echo -e "Available Memory\t:$AVAILABLE_MEM MB"
echo -e "Buffer+Cache Memory\t:$BUFFCACHE_MEM MB"
echo -e "Free Memory\t\t:$FREE_MEM MB"
echo -e "Memory Usage Percentage\t:$MEM_USAGE_PERCENT %"
# if available or (free+buffer+cache) is close to 0
# We will warn the user if it's below 100 MiB
if [ $AVAILABLE_MEM -lt 100 -o $YIELD_MEM -lt 100 ] ; then
echo "Available Memory or the free and buffer+cache Memory is too low!"
echo "Unhealthy Memory!"
# if kernel employed OOM Killer process
elif dmesg | grep oom-killer > /dev/null ; then
echo "System is critically low on memory!"
else
echo -e "\nMEMORY OK\n........................................"
fi
}
function cpu_util ()
{
# number of cpu cores
CORES=$(nproc)
# cpu load average of 15 minutes
LOAD_AVERAGE=$(uptime | awk '{print $10}')
LOAD_PERCENT=$(bc <<<"scale=0; $LOAD_AVERAGE * 100")
echo -e "........................................\nCPU UTILIZATION\n"
echo -e "Number of Cores\t:$CORES\n"
echo -e "Total CPU Load Average for the past 15 minutes\t:$LOAD_AVERAGE"
echo -e "CPU Load %\t\t\t\t\t:$LOAD_PERCENT"
echo -e "\nThe load average reading takes into account all the core(s) present in the system"
# if load average is equal to the number
# of cores, print warning
if [[ $(echo "if (${LOAD_AVERAGE} == ${CORES}) 1 else 0" | bc) -eq 1 ]] ; then
echo "Load average not ideal."
elif [[ $(echo "if (${LOAD_AVERAGE} > ${CORES}) 1 else 0" | bc) -eq 1 ]] ; then
echo "Critical! Load average is too high!"
else
echo -e "\nCPU LOAD OK"
fi
# capturing the second iteration of top and storing the CPU% id.
IDLE=$(top -b -n2 | awk '/Cpu/ {print $8}' | tail -1)
CPU_USAGE_PERCENT=$(bc <<<"scale=2; 100 - $IDLE/$CORES")
echo -e "\nCPU Usage %\t:$CPU_USAGE_PERCENT\n........................................"
}
function disk_util ()
{
ROOT_DISK_USED=$(df -h | grep -w '/' | awk '{print $5}')
ROOT_DISK_USED=$(printf %s "$ROOT_DISK_USED" | tr -d [="%"=])
ROOT_DISK_AVAIL=$(( 100 - $ROOT_DISK_USED ))
HOME_DISK_USED=$(df -h | grep -w '/home' | awk '{print $5}')
HOME_DISK_USED=$(printf %s "$HOME_DISK_USED" | tr -d [="%"=])
HOME_DISK_AVAIL=$(( 100 - $HOME_DISK_USED ))
echo -e "........................................\nDISK UTILIZATION\n"
echo -e "Root(/) Used\t\t:$ROOT_DISK_USED%"
echo -e "Root(/) Available\t:$ROOT_DISK_AVAIL%\n"
echo -e "Home(/home) Used\t:$HOME_DISK_USED%"
echo -e "Home(/home) Available\t:$HOME_DISK_AVAIL%"
# print warning if any of the disk is used above 95%
if [ $ROOT_DISK_USED -ge 95 -o $HOME_DISK_USED -ge 95 ] ; then
echo -e "\nDisk is almost full! Free up some space!"
else
echo -e "\nDISK OK"
fi
}
# if args have been specified, then show the
# correct syntax to the user
if [ $# -gt 0 ] ; then
echo "Invalid Syntax!"
echo "The valid syntax is ./$(basename $0)"
exit 1
fi
function main ()
{
memory_util
cpu_util
disk_util
}
main
Run the Script
$ ./sysperform.sh

Displaying the system performance report and analyzing it
Handles invalid cases as well

The script doesn’t take any argument
Similar Reads
Shell Scripting - System Logging
Shell scripting is a way of automating tasks and operations on a computer system by writing scripts and programs in a shell or terminal environment. These scripts can run commands, access system resources, and process data. Shell scripts are often used to automate repetitive tasks, such as backups,
9 min read
Shell Scripting - True Command
A shell provides an interface with the help of which users can interact with the system easily. To directly interact with a shell, we use an operating system. On a Unix-based operating system, every time we write a command using a terminal, we interact with the system. To interpret or analyze Unix c
3 min read
Shell Scripting - How to view Processes?
In this article, let's explore how we can view current processes running on a Linux Server. Linux machine gives users the option of multitasking hence naturally there will be multiple processes running on a session and also these processes are important fundamental components of Linux OS, Hence Syst
4 min read
Shell Script to Check Disk Space Usage
Disk usage is a report generated by the Linux system about different disks available or created on the secondary memory. These disks are also known as partitions, they have their isolated filesystem. This facility provides us the measurements of different labels or features like Used space, Free spa
3 min read
Performance vs Scalability in System Design
Performance vs Scalability in System Design explores how systems balance speed (performance) and ability to handle growth (scalability). Imagine a race car (performance) and a bus (scalability). The car zooms quickly but can't carry many passengers, while the bus carries lots but moves slower. Simil
6 min read
Shell Scripting - Define #!/bin/bash
A shell provides an interface to connect with the system. When we use an operating system, we indirectly interact with the shell. While using a terminal every time on any Linux distribution system, we interact with the shell. The main function of the shell is to interpret or analyze Unix commands. A
3 min read
Shell Script to Check Hard Disk Revolutions Per Minute (RPM) Speed
RPM is an acronym for Revolution Per Minute. RPM is the number of revolutions a hard disk makes in a single minute. Normally, the higher the RPM of a disk the better it is, however with higher RPM comes higher cost. Below is a shell script to check the RPM of a hard disk. Using hdparm command: hdpar
2 min read
Introduction to Linux Shell and Shell Scripting
If we are using any major operating system, we are indirectly interacting with the shell. While running Ubuntu, Linux Mint, or any other Linux distribution, we are interacting with the shell by using the terminal. In this article we will discuss Linux shells and shell scripting so before understandi
7 min read
How to check the execution time of Python script ?
In this article, we will discuss how to check the execution time of a Python script. There are many Python modules like time, timeit and datetime module in Python which can store the time at which a particular section of the program is being executed. By manipulating or getting the difference betwee
6 min read
Performance Testing vs Functional Testing
Testing is an important phase in the software development life cycle. It checks and validates all kinds of programs to determine malfunctions that could introduce trouble later or in the future such as processing issues, usability, and so on. These problems are very dangerous from a business point o
3 min read