Monitoring our environment is crucial especially when deploying a new application. Nowadays, companies use open source solutions to monitor system resources on a daily basis. However, when it comes to monitor for a certain amount of time for testing purposes, bash scripting comes handy.
In this tutorial, we are going to write a shell or bash script to monitor output a table with three columns showing the percentages of Memory, Disk and CPU used on our machine. The script is going to run for a certain amount of time every 1 second and save the date to a log file in a table form. Later on, the data file can then be imported into a Microsoft Excel sheet for analysis and graphing.
You can use this tool to know what kind of plan you would like to get for your AWS Lightsail instance when migrating your WordPress
Let’s get started!
The script is basically made up of three main parts:
1. Bash Script to Monitor Memory:
free -m | awk 'NR==2{printf "%.2f%%\t\t", $3*100/$2 }'
9.24%
free -m is a command used to show the memory used and free and it gives the below output:
[root@localhost tmp]# free -m
total used free shared buffers cached
Mem: 996 92 904 0 11 31
-/+ buffers/cache: 49 947
Swap: 1583 0 1583
However, what we need from the above output is the total and used memory from the second line. A way to extract data from a given output is by using AWK.
AWK is an programming language used for text processing and data extraction. It is a standard feature of most UNIX systems. awk ‘NR==2’ extracts data form the second line. the $3 and $2 act as holders for the used and total values respectively.
2. Bash Script to Monitor Disk:
df -h | awk '$NF=="/"{printf "%s\t\t", $5}'
7%
The second command outputs the percentage of disk used. df -h outputs data related to disk usage and partitions.
[root@localhost tmp]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root 14G 814M 12G 7% /
tmpfs 499M 0 499M 0% /dev/shm
/dev/sda1 485M 32M 428M 7% /boot
awk ‘$NF outputs the number of fields. However, df -h | awk ‘$NF==”/” will go to that line which contains the character “/”. The $5 will select the field number five from that line. This ensures that the command extracts the correct percentage of disk used (which is %7 in our case).
3. Bash Script to Monitor CPU
top -bn1 | grep load | awk '{printf "%.2f%%\t\t\n", $(NF-2)}'
The top -bn1 command will execute the top command only once (n1 = one iteration) the “b” is used when we want to use “top” in a bash script or to output its data to a file.
“grep load” will output the line which contains the string “load”. $(NF-2) will count the number of fields on that line and decrement 2, thus outputs field #10, or the first 0.00 in the below output.
[root@localhost tmp]# top -bn1 | grep load
top - 19:31:25 up 1:47, 1 user, load average: 0.00, 0.00, 0.00
After going through the basic parts of the bash scripts, we need to save these commands into variables MEMORY, DISK, and CPU:
MEMORY=$(free -m | awk 'NR==2{printf "%.2f%%\t\t", $3*100/$2 }')
DISK=$(df -h | awk '$NF=="/"{printf "%s\t\t", $5}')
CPU=$(top -bn1 | grep load | awk '{printf "%.2f%%\t\t\n", $(NF-2)}')
We need the script to run for a certain amount of time, let’s say for an hour. In order to do this, we need to use the “while do” loop, with a delay of x seconds after each loop since or depending on your testing:
end=$((SECONDS+3600))
while [ $SECONDS -lt $end ]; do
echo "$MEMORY$DISK$CPU"
sleep 5
done
In order to run a loop for a certain amount of time, we can define a variable $end which takes the current number of seconds from the time at which the bash script started, hence SECONDS, and adds a number to the current seconds. So an hour would be 3600 seconds.
The second line of the above code snippet states that the while loop will keep executing as long as the current number of seconds is less than the (current number of seconds + 3600). So, we have defined a starting time and an ending time for the loop, in addition to a sleep time that will pause each loop for 5 seconds. Inside the loop is the three variables being assigned every 5 seconds new values, and the echo “$MEMORY$DISK$CPU” which will output the three resource usages.
The complete code is below:
#! /bin/bash
printf "Memory\t\tDisk\t\tCPU\n"
end=$((SECONDS+3600))
while [ $SECONDS -lt $end ]; do
MEMORY=$(free -m | awk 'NR==2{printf "%.2f%%\t\t", $3*100/$2 }')
DISK=$(df -h | awk '$NF=="/"{printf "%s\t\t", $5}')
CPU=$(top -bn1 | grep load | awk '{printf "%.2f%%\t\t\n", $(NF-2)}')
echo "$MEMORY$DISK$CPU"
sleep 5
done
The above code will output the following:
[root@localhost tmp]# ./stats.sh
Memory Disk CPU
9.34% 7% 0.00%
9.34% 7% 0.00%
9.34% 7% 0.00%
9.34% 7% 0.00%
^C[root@localhost tmp]#
You can always output the data to a log file:
[root@localhost tmp]# ./stats.sh >> log.txt
Stress Test
Since we barley have any load on the machine, we can use a stress tester to cause the CPU and Memory to load for some time. You can read the man page for the tool here
Issue the below command (on CentOS):
root@localhost tmp]# yum install stress
Failed to set locale, defaulting to C
Loaded plugins: fastestmirror
Determining fastest mirrors
epel/metalink | 4.2 kB 00:00
* base: ba.mirror.garr.it
* epel: ftp.riken.jp
* extras: centos.fastbull.org
* updates: centos.fastbull.org
base | 3.7 kB 00:00
epel | 4.3 kB 00:00
epel/primary_db | 5.9 MB 00:37
extras | 3.4 kB 00:00
extras/primary_db | 37 kB 00:00
updates | 3.4 kB 00:00
updates/primary_db | 5.2 MB 00:30
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package stress.x86_64 0:1.0.4-4.el6 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
===================================================================================================
Package Arch Version Repository Size
===================================================================================================
Installing:
stress x86_64 1.0.4-4.el6 epel 36 k
Transaction Summary
===================================================================================================
Install 1 Package(s)
Total download size: 36 k
Installed size: 89 k
Is this ok [y/N]: y
Downloading Packages:
stress-1.0.4-4.el6.x86_64.rpm | 36 kB 00:01
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Installing : stress-1.0.4-4.el6.x86_64 1/1
Verifying : stress-1.0.4-4.el6.x86_64 1/1
Installed:
stress.x86_64 0:1.0.4-4.el6
Complete!
Now we can use the command “stress” to load our machine. For example, a load average of four is imposed on the system by specifying two CPU-bound processes, one I/O-bound process, and one memory allocator process as follows. The below stress test will run for 1 hour.
[root@localhost tmp]# stress -c 2 -i 1 -m 1 --vm-bytes 128M -t 3600s
stress: info: [1574] dispatching hogs: 2 cpu, 1 io, 1 vm, 0 hdd
stress: info: [1574] successful run completed in 3600s
[root@localhost tmp]# ./stats.sh
Memory Disk CPU
20.48% 7% 1.21%
20.48% 7% 1.02%
20.48% 7% 0.94%
21.89% 7% 1.18%
20.68% 7% 1.41%
22.09% 7% 1.62%
24.10% 7% 1.81%
24.90% 7% 1.98%
32.93% 7% 2.14%
30.32% 7% 2.29%
20.58% 7% 2.63%
27.91% 7% 2.82%
20.48% 7% 2.59%
20.48% 7% 2.38%
20.48% 7% 2.19%
20.48% 7% 2.02%
20.48% 7% 1.86%
This concludes our tutorial for how to create a very basic and useful bash script for all the System Administrators out there.
Leave a Reply