Shell Scripting to check System Performance
Last Updated :
23 Jul, 2025
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 itHandles 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 - 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 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
3 min read
How to check the Execution Time of Python script ? Checking the execution time of a python script helps you measure how long a piece of code takes to run. This is useful for analyzing performance, especially when working with large data or complex algorithms.Let's explore different ways to check execution time of python.Using timeit moduletimeit mod
3 min read
SAR command in Linux to monitor system performance sar (System Activity Report) It can be used to monitor Linux system's resources like CPU usage, Memory utilization, I/O devices consumption, Network monitoring, Disk usage, process and thread allocation, battery performance, Plug and play devices, Processor performance, file system and more. Linux s
9 min read
Menu Driven Shell Script to Check Memory and Disk Usages In Linux most of the time, we automate things using the bash scripts. Some script has only one functionality, but some script can do more than one functions. For that, we have to provide the menu to select the option which function should be performed now. This script is called as Menu-Driven Progra
4 min read