|
| 1 | +#!/bin/bash |
| 2 | +# monitor.sh <cpu_max> <cpu_avg> <mem_max_MB> <mem_avg_MB> <duration_sec> <cmd> |
| 3 | + |
| 4 | +cpu_max=$1 |
| 5 | +cpu_avg=$2 |
| 6 | +mem_max=$3 |
| 7 | +mem_avg=$4 |
| 8 | +duration=$5 |
| 9 | +shift 5 |
| 10 | +cmd="$@" |
| 11 | + |
| 12 | +start_time=$(date +%s) |
| 13 | +end_time=$((start_time + duration)) |
| 14 | + |
| 15 | +# Start the command |
| 16 | +$cmd & |
| 17 | +pid=$! |
| 18 | +echo "Monitoring PID $pid for $duration seconds..." |
| 19 | +sleep 5 |
| 20 | + |
| 21 | +# Cleanup handler |
| 22 | +cleanup() { |
| 23 | + echo "Cleaning up... killing $pid" |
| 24 | + kill $pid 2>/dev/null |
| 25 | +} |
| 26 | +trap cleanup EXIT |
| 27 | + |
| 28 | +# Stats accumulators |
| 29 | +cpu_sum=0 |
| 30 | +cpu_count=0 |
| 31 | +cpu_peak=0 |
| 32 | +mem_sum=0 |
| 33 | +mem_peak=0 |
| 34 | + |
| 35 | +last_minute=$start_time |
| 36 | + |
| 37 | +while kill -0 $pid 2>/dev/null && [ $(date +%s) -lt $end_time ]; do |
| 38 | + # Get stats |
| 39 | + stats=$(ps -p $pid -o %cpu= -o rss= -o nlwp= 2>/dev/null) |
| 40 | + cpu=$(echo $stats | awk '{print $1}') |
| 41 | + mem_kb=$(echo $stats | awk '{print $2}') |
| 42 | + threads=$(echo $stats | awk '{print $3}') |
| 43 | + mem_mb=$(echo "scale=2; $mem_kb / 1024" | bc) |
| 44 | + |
| 45 | + # Update accumulators |
| 46 | + cpu_sum=$(echo "$cpu_sum + $cpu" | bc) |
| 47 | + cpu_count=$((cpu_count + 1)) |
| 48 | + (( $(echo "$cpu > $cpu_peak" | bc -l) )) && cpu_peak=$cpu |
| 49 | + (( $(echo "$mem_mb > $mem_peak" | bc -l) )) && mem_peak=$mem_mb |
| 50 | + mem_sum=$(echo "$mem_sum + $mem_mb" | bc) |
| 51 | + |
| 52 | + # Per-second live print |
| 53 | + printf "[LIVE] CPU=%.2f%% MEM=%.2fMB Threads=%s\n" "$cpu" "$mem_mb" "$threads" |
| 54 | + |
| 55 | + now=$(date +%s) |
| 56 | + # Every 60s print summary |
| 57 | + if (( now - last_minute >= 60 )); then |
| 58 | + avg_cpu=$(echo "scale=2; $cpu_sum / $cpu_count" | bc) |
| 59 | + avg_mem=$(echo "scale=2; $mem_sum / $cpu_count" | bc) |
| 60 | + echo "=== Minute Summary ($(date '+%Y-%m-%d %H:%M:%S')) ===" |
| 61 | + printf "Avg CPU: %.2f%% Max CPU: %.2f%%\n" "$avg_cpu" "$cpu_peak" |
| 62 | + printf "Avg MEM: %.2fMB Max MEM: %.2fMB\n" "$avg_mem" "$mem_peak" |
| 63 | + echo "Threads: $threads" |
| 64 | + last_minute=$now |
| 65 | + fi |
| 66 | + |
| 67 | + sleep 5 |
| 68 | +done |
| 69 | + |
| 70 | +# Final summary |
| 71 | +avg_cpu=$(echo "scale=2; $cpu_sum / $cpu_count" | bc) |
| 72 | +avg_mem=$(echo "scale=2; $mem_sum / $cpu_count" | bc) |
| 73 | +echo "=== Final Results ===" |
| 74 | +printf "Avg CPU: %.2f%% Max CPU: %.2f%% (limit avg=%.2f, max=%.2f)\n" "$avg_cpu" "$cpu_peak" "$cpu_avg" "$cpu_max" |
| 75 | +printf "Avg MEM: %.2fMB Max MEM: %.2fMB (limit avg=%.2f, max=%.2f)\n" "$avg_mem" "$mem_peak" "$mem_avg" "$mem_max" |
| 76 | + |
| 77 | +# Check limits |
| 78 | +fail=0 |
| 79 | +if (( $(echo "$avg_cpu >= $cpu_avg" | bc -l) )); then |
| 80 | + echo "FAIL: Average CPU ${avg_cpu}% exceeds limit ${cpu_avg}%" |
| 81 | + fail=1 |
| 82 | +fi |
| 83 | +if (( $(echo "$cpu_peak >= $cpu_max" | bc -l) )); then |
| 84 | + echo "FAIL: Max CPU ${cpu_peak}% exceeds limit ${cpu_max}%" |
| 85 | + fail=1 |
| 86 | +fi |
| 87 | +if (( $(echo "$avg_mem >= $mem_avg" | bc -l) )); then |
| 88 | + echo "FAIL: Average MEM ${avg_mem}MB exceeds limit ${mem_avg}MB" |
| 89 | + fail=1 |
| 90 | +fi |
| 91 | +if (( $(echo "$mem_peak >= $mem_max" | bc -l) )); then |
| 92 | + echo "FAIL: Max MEM ${mem_peak}MB exceeds limit ${mem_max}MB" |
| 93 | + fail=1 |
| 94 | +fi |
| 95 | + |
| 96 | +if [ $fail -eq 0 ]; then |
| 97 | + echo "PASS: Resource usage within limits" |
| 98 | +fi |
| 99 | + |
| 100 | +exit $fail |
0 commit comments