resource-monitor.sh 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #!/bin/bash
  2. # Resource monitoring script for apt-mirror, nginx, and admin app
  3. # Returns JSON with process resource usage
  4. # Function to get process info by name
  5. get_process_info() {
  6. local process_name=$1
  7. local display_name=$2
  8. # Find process by name with more specific patterns for Docker
  9. local pid=""
  10. case $process_name in
  11. "apt-mirror")
  12. # Look for the actual Python apt-mirror process
  13. pid=$(pgrep -f "/usr/bin/python3.*apt-mirror" | head -1)
  14. if [ -z "$pid" ]; then
  15. pid=$(pgrep -f "python3.*apt-mirror" | head -1)
  16. fi
  17. if [ -z "$pid" ]; then
  18. pid=$(pgrep -f "python.*apt-mirror" | head -1)
  19. fi
  20. ;;
  21. "nginx")
  22. # Look for nginx worker process
  23. pid=$(pgrep -f "nginx.*worker process" | head -1)
  24. if [ -z "$pid" ]; then
  25. # If no worker found, use master process
  26. pid=$(pgrep -f "nginx.*master" | head -1)
  27. fi
  28. if [ -z "$pid" ]; then
  29. pid=$(pgrep -f "nginx" | head -1)
  30. fi
  31. ;;
  32. "react-router-serve")
  33. # Look for actual node process running react-router-serve
  34. pid=$(pgrep -f "node.*react-router-serve" | head -1)
  35. if [ -z "$pid" ]; then
  36. pid=$(pgrep -f "react-router-serve.*index.js" | head -1)
  37. fi
  38. if [ -z "$pid" ]; then
  39. pid=$(pgrep -f "node.*admin" | head -1)
  40. fi
  41. ;;
  42. *)
  43. pid=$(pgrep -f "$process_name" | head -1)
  44. ;;
  45. esac
  46. if [ -z "$pid" ]; then
  47. echo "{\"name\":\"$display_name\",\"status\":\"not_running\",\"ramMb\":0,\"cpuPercent\":0}"
  48. return
  49. fi
  50. # Debug: Show what process we found
  51. echo "Debug: Found process $display_name with PID $pid" >&2
  52. ps -p "$pid" -o pid,ppid,pcpu,pmem,comm,args --no-headers >&2
  53. # Get process stats using ps with more reliable options for containers
  54. local stats=$(ps -p "$pid" -o pid,ppid,pcpu,pmem,comm --no-headers 2>/dev/null)
  55. if [ -z "$stats" ]; then
  56. echo "{\"name\":\"$display_name\",\"status\":\"not_found\",\"ramMb\":0,\"cpuPercent\":0}"
  57. return
  58. fi
  59. # Parse stats (format: PID PPID %CPU %MEM COMMAND)
  60. local cpu_percent=$(echo "$stats" | awk '{print $3}')
  61. local ram_percent=$(echo "$stats" | awk '{print $4}')
  62. # Debug: Show parsed values
  63. echo "Debug: $display_name - CPU: $cpu_percent%, RAM: $ram_percent%" >&2
  64. # If ps doesn't work well in container, try alternative methods
  65. if [ -z "$cpu_percent" ] || [ "$cpu_percent" = "0.0" ] || [ "$cpu_percent" = "0" ]; then
  66. # Set locale to C for consistent decimal formatting
  67. export LC_NUMERIC=C
  68. # Try using top for more accurate CPU stats
  69. local top_cpu=$(top -bn1 -p "$pid" 2>/dev/null | tail -1 | awk '{print $9}')
  70. if [ -n "$top_cpu" ] && [ "$top_cpu" != "0.0" ] && [ "$top_cpu" != "0,0" ]; then
  71. cpu_percent=$top_cpu
  72. else
  73. # Use a simple approach - if process is running, give it a small CPU value
  74. cpu_percent=0.1
  75. fi
  76. fi
  77. if [ -z "$ram_percent" ] || [ "$ram_percent" = "0.0" ] || [ "$ram_percent" = "0" ]; then
  78. # Try using /proc for memory stats
  79. if [ -f "/proc/$pid/status" ]; then
  80. # Try VmSize first (total virtual memory), then VmRSS (resident set)
  81. local vm_size=$(grep "VmSize:" "/proc/$pid/status" | awk '{print $2}')
  82. local vm_rss=$(grep "VmRSS:" "/proc/$pid/status" | awk '{print $2}')
  83. echo "Debug: $display_name - VmSize: $vm_size KB, VmRSS: $vm_rss KB" >&2
  84. if [ -n "$vm_size" ] && [ "$vm_size" -gt 0 ]; then
  85. # Convert KB to MB for VmSize
  86. ram_mb=$((vm_size / 1024))
  87. elif [ -n "$vm_rss" ] && [ "$vm_rss" -gt 0 ]; then
  88. # Convert KB to MB for VmRSS
  89. ram_mb=$((vm_rss / 1024))
  90. fi
  91. # If we got a reasonable RAM value, calculate percentage
  92. if [ -n "$ram_mb" ] && [ "$ram_mb" -gt 0 ]; then
  93. local total_ram_mb=$(free -m | awk 'NR==2{print $2}')
  94. if [ "$total_ram_mb" -gt 0 ]; then
  95. ram_percent=$(echo "scale=2; $ram_mb * 100 / $total_ram_mb" | bc -l 2>/dev/null)
  96. fi
  97. fi
  98. fi
  99. fi
  100. # Convert RAM percentage to MB (assuming total RAM is available)
  101. local total_ram_mb=$(free -m | awk 'NR==2{print $2}')
  102. # Set locale to C to ensure decimal points instead of commas
  103. export LC_NUMERIC=C
  104. local ram_mb_calc=$(echo "$ram_percent * $total_ram_mb / 100" | bc -l 2>/dev/null | cut -d. -f1)
  105. # Use calculated RAM if we have it, otherwise use direct measurement
  106. if [ -n "$ram_mb" ] && [ "$ram_mb" -gt 0 ]; then
  107. # Use the direct measurement from /proc
  108. :
  109. else
  110. ram_mb=$ram_mb_calc
  111. fi
  112. # Ensure we have valid numbers
  113. if [ -z "$ram_mb" ] || [ "$ram_mb" = "0" ]; then
  114. ram_mb=0
  115. fi
  116. if [ -z "$cpu_percent" ]; then
  117. cpu_percent=0
  118. fi
  119. echo "Debug: $display_name - Final RAM: $ram_mb MB, CPU: $cpu_percent%" >&2
  120. echo "{\"name\":\"$display_name\",\"status\":\"running\",\"ramMb\":$ram_mb,\"cpuPercent\":$cpu_percent}"
  121. }
  122. # Function to get system total RAM
  123. get_system_ram() {
  124. local total_ram_mb=$(free -m | awk 'NR==2{print $2}')
  125. echo "$total_ram_mb"
  126. }
  127. # Function to get system total CPU usage
  128. get_system_cpu() {
  129. # Set locale to C to ensure decimal points instead of commas
  130. export LC_NUMERIC=C
  131. local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
  132. echo "$cpu_usage"
  133. }
  134. # Main execution
  135. main() {
  136. # Get system info
  137. local total_ram=$(get_system_ram)
  138. local system_cpu=$(get_system_cpu)
  139. # Get process info for each service
  140. local apt_mirror_info=$(get_process_info "apt-mirror" "apt-mirror")
  141. local nginx_info=$(get_process_info "nginx" "nginx")
  142. local admin_info=$(get_process_info "react-router-serve" "admin-app")
  143. # Create JSON response
  144. cat << EOF
  145. {
  146. "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  147. "system": {
  148. "totalRamMb": $total_ram,
  149. "cpuPercent": $system_cpu
  150. },
  151. "processes": [
  152. $apt_mirror_info,
  153. $nginx_info,
  154. $admin_info
  155. ]
  156. }
  157. EOF
  158. }
  159. # Run main function
  160. main