Implementing CPU, Memory, and Disk Monitoring with Shell Scripts
Implementing CPU, Memory, and Disk Monitoring with Shell Scripts
In modern operations management systems, real-time monitoring of server resource status serves as the cornerstone for ensuring business continuity. Traditional passive alert modes often suffer from latency, failing to issue warnings before resources are exhausted. By writing efficient shell scripts, we can leverage Linux's powerful command-line toolset to actively collect and visualize CPU, memory, and disk utilization rates. This article delves into how to construct a lightweight, scalable server monitoring solution using shell scripts, helping operations personnel quickly grasp the health status of their systems.
Before writing monitoring scripts, it is essential to understand how the Linux kernel exposes hardware resource usage at its core level. The Linux kernel provides rich interfaces through the /proc filesystem, allowing user-space programs to read kernel data directly without installing additional agent software.
- CPU Monitoring: Primarily obtained via the
/proc/statfile, which contains statistical information for each CPU core. This file records various CPU usage states over different time intervals (such asusfor user mode,syfor system mode, andidfor idle state). By calculating the difference in values between two consecutive reads divided by the elapsed time, one can derive the true CPU utilization rate. - Memory Monitoring: Core data resides in the
/proc/meminfofile. Key metrics includeMemTotal(total memory),MemFree(free memory), andMemAvailable(truly available memory). The latter provides a more accurate reflection of whether the system is at risk of running out of memory compared to the former, because Linux supports swap partitions; free memory does not necessarily mean it can be used immediately. - Disk Monitoring: The most common tool is the
df -hcommand, which reads/proc/mountsor filesystem metadata to calculate used space, total capacity, and percentage for each mount point. For scenarios requiring finer-grained information, one can also combine this withiostatto view I/O wait times.
Script Implementation: CPU Utilization Calculation Logic
Calculating CPU utilization is arguably the most challenging part of shell monitoring due to its reliance on cross-temporal state differential operations. Below is a simplified example of CPU monitoring logic:
- Read Data: Call
cat /proc/statto retrieve the current CPU statistics line. - Extract Fields: Parse the output to extract numerical values for fields such as
us,sy,id, andwa(wait time). - Timestamp Calculation: Use
date +%sto obtain a second-level timestamp, utilizing the difference between two reads as the denominator. - Differential Operation: Subtract current values from previous round's values to get increments.
- Percentage Conversion: Divide the increment of (user mode + system mode + wait time) by the total increment plus idle increment, then multiply by 100.
It is important to note that since /proc/stat refreshes once per second by default, the calculated CPU utilization typically represents an average value. This holds significant reference for determining whether sudden workload spikes are excessive.
Script Implementation: Memory and Disk Status Collection
Compared to CPU monitoring, memory and disk logic is more direct, primarily relying on parsing text files or executing standard commands.
Memory Monitoring Example
By reading /proc/meminfo, extract the MemAvailable field and calculate utilization. If available memory drops below 20% of total memory, trigger a warning mechanism. This method avoids false positives caused by swap partitions and is recommended for production environments.
Disk Monitoring Example
Utilize the df -h command in conjunction with regular expressions or the awk tool for parsing. The script will iterate through all mount points (excluding tmpfs and devtmpfs) to identify partitions exceeding a threshold (e.g., 85%) and output their specific paths along with remaining space sizes.
Practical Exercise: Comprehensive Monitoring Script Development
Integrating the above logic into a complete shell script can significantly boost operational efficiency. Below is a basic implementation framework named system_monitor.sh:
#!/bin/bash
# Define thresholds
CPU_THRESHOLD=80
MEM_THRESHOLD=20
DISK_THRESHOLD=85
echo "=== Starting System Health Check ===" | tee /dev/stderr
# --- CPU Monitoring ---
read -r cpu_line < /proc/stat
prev_cpu_line=$(cat /proc/stat | head -n1)
# Extract current values (us, sy, id, wa)
curr_us=$(echo $cpu_line | awk '{print $2}')
curr_sy=$(echo $cpu_line | awk '{print $3}')
curr_id=$(echo $cpu_line | awk '{print $4}')
curr_wa=$(echo $cpu_line | awk '{print $5}')
# Extract previous round values
prev_us=$(echo $prev_cpu_line | awk '{print $2}')
prev_sy=$(echo $prev_cpu_line | awk '{print $3}')
prev_id=$(echo $prev_cpu_line | awk '{print $4}')
prev_wa=$(echo $prev_cpu_line | awk '{print $5}')
# Calculate time difference (simplified version, assuming fixed interval of 1 second)
time_diff=1
user_time=$((curr_us - prev_us))
sys_time=$((curr_sy - prev_sy))
idle_time=$((curr_id - prev_id))
wait_time=$((curr_wa - prev_wa))
total_active=$((user_time + sys_time + wait_time))
total_idle=$idle_time
total_cpu=$((total_active + total_idle))
cpu_usage=$(awk "BEGIN {printf \"%.2f\", ($total_active / $total_cpu) * 100}")
if (( $(echo "$cpu_usage > $CPU_THRESHOLD" | bc -l) )); then
echo "[Warning] CPU utilization too high: ${cpu_usage}%"
fi
# --- Memory Monitoring ---
mem_available=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
mem_used=$((mem_total - mem_available))
mem_percent=$(awk "BEGIN {printf \"%.2f\", ($mem_used / $mem_total) * 100}")
if (( $(echo "$mem_percent > $MEM_THRESHOLD" | bc -l) )); then
echo "[Warning] Memory utilization too high: ${mem_percent}%"
fi
# --- Disk Monitoring ---
df --output=source,pcent,used | tail -n +2 | awk -v thresh=$DISK_THRESHOLD '$3 > thresh {print "Disk [" $1 "] Usage Rate:" $4 "%"}'
echo "=== Check Completed ==="
Deployment and Maintenance: Logging and Scalability
After writing the script, details regarding actual deployment often determine its long-term value. First, it is recommended to redirect output to a log file (e.g., /var/log/system_monitor.log) for historical trend analysis and fault tracing. Secondly, to adapt to multi-core CPU environments or complex mount structures, the script should enhance robustness in handling awk and grep, preventing parsing errors caused by format changes.
Furthermore, this script exhibits good scalability. If network bandwidth monitoring (via /proc/net/dev) or load average (uptime command) is required, new detection modules can be added following the existing modular logic without major restructuring. For scenarios requiring higher frequency collection, consider running the script within a cron scheduled task or integrating it into mature monitoring systems like Prometheus Node Exporter, using shell scripts as a preliminary data cleaning layer to further reduce system load.
Conclusion
Shell scripts, due to their simplicity and native support, have become the preferred tool for basic resource monitoring in Linux environments. By mastering techniques for reading /proc filesystems and fundamental text processing commands, operations personnel can construct real-time resource awareness capabilities at a low cost. This solution is not only applicable to single-server setups but its logical architecture can also be easily migrated to containerized environments or cluster management scenarios, providing solid data support for automated operations systems.