#!/bin/bash # System Monitoring and Health Check # Part of Linux System Tuning Suite set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" LOG_DIR="/var/log/system-tuning" METRICS_FILE="$LOG_DIR/metrics.log" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log() { echo -e "${BLUE}[$(date '+%H:%M:%S')]${NC} $1" } warn() { echo -e "${YELLOW}[WARNING]${NC} $1" } error() { echo -e "${RED}[ERROR]${NC} $1" } success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } show_usage() { cat << EOF System Monitoring Tool Usage: $0 [OPTIONS] [MODE] OPTIONS: -h, --help Show this help message -l, --log Log metrics to file -d, --duration SEC Monitoring duration in seconds (default: continuous) MODES: status Show current status (default) live Live monitoring with updates benchmark Run performance benchmarks health Health check of optimizations compare Compare performance before/after export Export metrics for external analysis EXAMPLES: $0 # Show current status $0 live # Live monitoring $0 health # Health check $0 benchmark # Run benchmarks EOF } setup_logging() { if [[ ! -d "$LOG_DIR" ]]; then sudo mkdir -p "$LOG_DIR" sudo chown $USER:$USER "$LOG_DIR" 2>/dev/null || true fi } collect_metrics() { local timestamp=$(date '+%Y-%m-%d %H:%M:%S') # Memory metrics local mem_info=$(free -m | awk '/^Mem:/{printf "total:%s,used:%s,free:%s,available:%s", $2,$3,$4,$7}') local swap_info=$(free -m | awk '/^Swap:/{printf "total:%s,used:%s,free:%s", $2,$3,$4}') # zram metrics local zram_info="" if [[ -e /dev/zram0 ]]; then local zram_size=$(cat /sys/block/zram0/disksize 2>/dev/null || echo "0") local zram_used=$(cat /sys/block/zram0/compr_data_size 2>/dev/null || echo "0") local zram_orig=$(cat /sys/block/zram0/orig_data_size 2>/dev/null || echo "0") zram_info="size:$zram_size,used:$zram_used,orig:$zram_orig" fi # tmpfs metrics local tmpfs_count=$(mount -t tmpfs | wc -l) local tmpfs_total=$(df -t tmpfs --total | tail -1 | awk '{print $2}' 2>/dev/null || echo "0") local tmpfs_used=$(df -t tmpfs --total | tail -1 | awk '{print $3}' 2>/dev/null || echo "0") # System load local load_avg=$(uptime | awk -F'load average:' '{print $2}' | sed 's/^ *//') # I/O stats local io_stats="" if command -v iostat >/dev/null 2>&1; then io_stats=$(iostat -d 1 2 | tail -n +4 | awk 'NR>1{tps+=$2; read+=$3; write+=$4} END{printf "tps:%.2f,read:%.2f,write:%.2f", tps, read, write}') fi cat << EOF { "timestamp": "$timestamp", "memory": {$mem_info}, "swap": {$swap_info}, "zram": {$zram_info}, "tmpfs": {"count": $tmpfs_count, "total_kb": $tmpfs_total, "used_kb": $tmpfs_used}, "load": "$load_avg", "io": {$io_stats} } EOF } show_status() { echo "🚀 System Tuning Status" echo "=======================" echo "" # Memory overview echo "💾 Memory Overview:" free -h | while IFS= read -r line; do echo " $line" done echo "" # zram status echo "🔄 Compression (zram):" if [[ -e /dev/zram0 ]]; then if command -v zramctl >/dev/null 2>&1; then zramctl | while IFS= read -r line; do echo " $line" done else local zram_size=$(cat /sys/block/zram0/disksize 2>/dev/null) local zram_used=$(cat /sys/block/zram0/compr_data_size 2>/dev/null) echo " Size: $((zram_size / 1024 / 1024 / 1024))GB" echo " Used: $((zram_used / 1024 / 1024))MB" fi else echo " Not configured" fi echo "" # tmpfs overview echo "📁 tmpfs Filesystems:" df -h -t tmpfs | while IFS= read -r line; do echo " $line" done echo "" # Kernel parameters echo "⚙️ Key Kernel Parameters:" echo " Swappiness: $(cat /proc/sys/vm/swappiness)" echo " Dirty ratio: $(cat /proc/sys/vm/dirty_ratio)" echo " Dirty background ratio: $(cat /proc/sys/vm/dirty_background_ratio)" echo " VFS cache pressure: $(cat /proc/sys/vm/vfs_cache_pressure)" echo "" # Service status echo "🔧 Services:" if systemctl is-enabled system-tuning.service >/dev/null 2>&1; then echo " System tuning service: ✅ ENABLED" else echo " System tuning service: ❌ DISABLED" fi # Performance score echo "" echo "📊 Performance Score: $(calculate_performance_score)/100" } live_monitoring() { local duration=${1:-0} local count=0 echo "📊 Live System Monitoring" echo "========================" echo "Press Ctrl+C to stop" echo "" while true; do clear echo "🔄 Live Monitor - $(date) (Update #$((++count)))" echo "==================================================" echo "" # Real-time metrics echo "Memory Usage:" free -h | head -2 echo "" echo "Top tmpfs by usage:" df -h -t tmpfs | sort -k5 -nr | head -5 | while IFS= read -r line; do echo " $line" done echo "" echo "zram compression ratio:" if [[ -e /dev/zram0 ]]; then local orig=$(cat /sys/block/zram0/orig_data_size 2>/dev/null || echo "0") local compr=$(cat /sys/block/zram0/compr_data_size 2>/dev/null || echo "0") if [[ $orig -gt 0 && $compr -gt 0 ]]; then local ratio=$(echo "scale=2; $orig / $compr" | bc -l 2>/dev/null || echo "N/A") echo " Compression: ${ratio}:1" echo " Original: $((orig / 1024 / 1024))MB" echo " Compressed: $((compr / 1024 / 1024))MB" else echo " No compression data available" fi else echo " zram not active" fi echo "" echo "System Load: $(uptime | awk -F'load average:' '{print $2}')" # Log metrics if enabled if [[ -f "$METRICS_FILE" ]]; then collect_metrics >> "$METRICS_FILE" fi sleep 2 # Exit if duration specified and reached if [[ $duration -gt 0 && $count -ge $duration ]]; then break fi done } run_benchmark() { echo "🏁 Performance Benchmark" echo "========================" echo "" log "Running memory performance tests..." # Memory speed test echo "Memory Performance:" if command -v dd >/dev/null 2>&1; then echo " Write test (1GB to tmpfs):" time (dd if=/dev/zero of=/tmp/benchmark-test bs=1M count=1024 2>/dev/null && sync) rm -f /tmp/benchmark-test echo "" fi # Application startup test echo "Application Startup Test:" if command -v time >/dev/null 2>&1; then echo " Shell startup:" time bash -c "exit" 2>&1 | grep real || echo " Could not measure" if command -v python3 >/dev/null 2>&1; then echo " Python startup:" time python3 -c "pass" 2>&1 | grep real || echo " Could not measure" fi fi echo "" # I/O performance if command -v iostat >/dev/null 2>&1; then echo "Current I/O performance:" iostat -x 1 1 | tail -n +4 fi echo "" success "Benchmark completed" } health_check() { echo "🏥 System Health Check" echo "=====================" echo "" local issues=0 local warnings=0 # Check zram if [[ -e /dev/zram0 ]]; then if swapon --show | grep -q zram0; then success "zram swap is active" else error "zram device exists but swap is not active" ((issues++)) fi else warn "zram not configured" ((warnings++)) fi # Check tmpfs mounts local tmpfs_count=$(mount -t tmpfs | wc -l) if [[ $tmpfs_count -gt 5 ]]; then success "Multiple tmpfs mounts detected ($tmpfs_count)" else warn "Few tmpfs mounts detected ($tmpfs_count) - consider more optimizations" ((warnings++)) fi # Check memory usage local mem_usage=$(free | awk '/^Mem:/{printf "%.0f", $3/$2*100}') if [[ $mem_usage -lt 80 ]]; then success "Memory usage is healthy ($mem_usage%)" else warn "High memory usage ($mem_usage%) - monitor for performance impact" ((warnings++)) fi # Check swap usage local swap_usage=$(free | awk '/^Swap:/{if($2>0) printf "%.0f", $3/$2*100; else print "0"}') if [[ $swap_usage -lt 50 ]]; then success "Swap usage is reasonable ($swap_usage%)" else warn "High swap usage ($swap_usage%) - consider adding more RAM" ((warnings++)) fi # Check service status if systemctl is-active system-tuning.service >/dev/null 2>&1; then success "System tuning service is running" else warn "System tuning service is not running" ((warnings++)) fi echo "" echo "Health Summary:" echo " Issues: $issues" echo " Warnings: $warnings" if [[ $issues -eq 0 && $warnings -eq 0 ]]; then success "System is optimally configured! 🎉" elif [[ $issues -eq 0 ]]; then warn "System is mostly optimized with $warnings minor warnings" else error "System has $issues issues that need attention" fi } calculate_performance_score() { local score=0 # Base score score=30 # zram bonus [[ -e /dev/zram0 ]] && score=$((score + 20)) # tmpfs bonus local tmpfs_count=$(mount -t tmpfs | wc -l) if [[ $tmpfs_count -gt 8 ]]; then score=$((score + 25)) elif [[ $tmpfs_count -gt 5 ]]; then score=$((score + 15)) fi # Kernel parameter optimization local swappiness=$(cat /proc/sys/vm/swappiness) [[ $swappiness -le 10 ]] && score=$((score + 10)) # Service bonus systemctl is-enabled system-tuning.service >/dev/null 2>&1 && score=$((score + 15)) echo $score } main() { local mode="status" local log_metrics=false local duration=0 # Parse arguments while [[ $# -gt 0 ]]; do case $1 in -h|--help) show_usage exit 0 ;; -l|--log) log_metrics=true shift ;; -d|--duration) duration="$2" shift 2 ;; status|live|benchmark|health|compare|export) mode="$1" shift ;; *) error "Unknown option: $1" show_usage exit 1 ;; esac done # Setup logging if requested if [[ "$log_metrics" == "true" ]]; then setup_logging fi # Execute requested mode case "$mode" in status) show_status ;; live) live_monitoring "$duration" ;; benchmark) run_benchmark ;; health) health_check ;; *) error "Mode '$mode' not implemented yet" exit 1 ;; esac } # Run if called directly if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" fi