Eliminate all bc command dependencies - replace with awk for portability

PROBLEM:
- bc command not installed on all systems (requires bc package)
- 30 instances across toolkit causing potential failures
- bc is external dependency for floating-point arithmetic

SOLUTION:
- Replaced all bc usage with awk (universally available)
- Pattern: echo "X * Y" | bc → awk "BEGIN {printf \"%.2f\", X * Y}"
- Pattern: (( $(echo "X > Y" | bc -l) )) → awk comparison + bash test

FILES MODIFIED (8 files, 30 bc instances eliminated):
1. lib/threat-intelligence.sh (1 fix)
   - Line 310: Load average to integer conversion

2. lib/reference-db.sh (2 fixes)
   - Line 554: CPU load percentage calculation
   - Line 570: TCP retransmission comparison

3. lib/php-analyzer.sh (5 fixes)
   - Line 138: Script duration comparison
   - Lines 391-395: OPcache hit rate + wasted memory + cached scripts
   - Line 479: OPcache hit rate threshold

4. modules/performance/hardware-health-check.sh (1 fix)
   - Line 264: CPU frequency conversion (KHz to GHz)

5. modules/performance/network-bandwidth-analyzer.sh (3 fixes)
   - Line 168: Daily bandwidth threshold (50 GiB)
   - Line 238: Bytes to MB conversion
   - Lines 388-390: TCP retransmission percentage

6. modules/performance/php-optimizer.sh (2 fixes)
   - Lines 457, 653: OPcache hit rate comparisons

7. modules/diagnostics/system-health-check.sh (10 fixes)
   - Lines 345-350: Load per core + threshold calculations
   - Lines 354-358: Load trend detection (3 comparisons)
   - Lines 367-406: Load critical/warning/elevated checks
   - Lines 828-829: TCP retransmission analysis
   - Line 901: Clock offset detection
   - Line 1692: Network stats TCP retrans percent

8. tools/toolkit-qa-check.sh (QA improvements)
   - Added --exclude="toolkit-qa-check.sh" to prevent self-scanning
   - Eliminates false positives from QA script itself

TECHNICAL DETAILS:
- All awk commands use BEGIN block for pure calculation
- printf formatting preserves decimal precision (%.2f, %.1f, %.0f)
- Error handling with 2>/dev/null || echo fallbacks
- Ternary operators for comparisons: (condition ? 1 : 0)

TESTING:
✓ QA scan shows 0 CRITICAL, 0 HIGH, 0 MEDIUM, 0 LOW issues
✓ All 30 bc instances eliminated
✓ No external dependencies beyond standard bash + awk
✓ Toolkit now portable to minimal Linux installations

IMPACT:
+ Eliminates bc package dependency
+ 100% portable (awk included in all Unix/Linux systems)
+ Same accuracy for floating-point calculations
+ Faster execution (awk is typically faster than bc)
+ Better error handling with fallback values
This commit is contained in:
cschantz
2025-12-03 20:49:46 -05:00
parent 8cc1384a85
commit 154afff7fc
8 changed files with 69 additions and 42 deletions
+12 -5
View File
@@ -135,7 +135,8 @@ analyze_slow_requests() {
total_count=$((total_count + 1))
# Track slowest occurrence per script
if [ -z "${slow_scripts[$script]}" ] || (( $(echo "${slow_scripts[$script]} < $duration" | bc -l) )); then
local is_slower=$(awk "BEGIN {print (${slow_scripts[$script]:-0} < $duration ? 1 : 0)}" 2>/dev/null || echo 1)
if [ -z "${slow_scripts[$script]}" ] || [ "$is_slower" -eq 1 ]; then
slow_scripts[$script]="$duration"
fi
fi
@@ -387,12 +388,15 @@ analyze_opcache_effectiveness() {
# Generate recommendation
local recommendation=""
local hit_rate_low=$(awk "BEGIN {print ($hit_rate < 90 ? 1 : 0)}" 2>/dev/null || echo 0)
local wasted_high=$(awk "BEGIN {print ($wasted > 5 ? 1 : 0)}" 2>/dev/null || echo 0)
local cached_high=$(awk "BEGIN {print ($cached_scripts > $max_cached * 0.8 ? 1 : 0)}" 2>/dev/null || echo 0)
if (( $(echo "$hit_rate < 90" | bc -l) )); then
if [ "$hit_rate_low" -eq 1 ]; then
recommendation="Hit rate below 90% - Increase opcache.memory_consumption"
elif (( $(echo "$wasted > 5" | bc -l) )); then
elif [ "$wasted_high" -eq 1 ]; then
recommendation="High wasted memory (${wasted}MB) - Consider increasing opcache.max_accelerated_files"
elif (( $(echo "$cached_scripts > $max_cached * 0.8" | bc -l) )); then
elif [ "$cached_high" -eq 1 ]; then
recommendation="Cached scripts at 80% capacity - Increase opcache.max_accelerated_files"
else
recommendation="OPcache performing optimally"
@@ -476,9 +480,12 @@ detect_php_config_issues() {
if [ "$status" = "DISABLED" ]; then
issues+="PERFORMANCE|HIGH|OPcache is disabled|Enable OPcache for 40-70% performance improvement"$'\n'
elif (( $(echo "$hit_rate < 90" | bc -l) )); then
else
local hit_rate_low=$(awk "BEGIN {print ($hit_rate < 90 ? 1 : 0)}" 2>/dev/null || echo 0)
if [ "$hit_rate_low" -eq 1 ]; then
issues+="PERFORMANCE|MEDIUM|OPcache hit rate is low (${hit_rate}%)|Increase opcache.memory_consumption"$'\n'
fi
fi
# ISSUE 7: Check FPM pool configuration
local pool_config
+3 -2
View File
@@ -551,7 +551,7 @@ db_is_system_under_load() {
# Consider system under load if CPU > 80% or memory > 90%
if [ -n "$cpu_load" ] && [ -n "$cpu_cores" ]; then
local load_percent=$(echo "scale=0; ($cpu_load / $cpu_cores) * 100" | bc 2>/dev/null || echo "0")
local load_percent=$(awk "BEGIN {printf \"%.0f\", ($cpu_load / $cpu_cores) * 100}" 2>/dev/null || echo "0")
if [ "$load_percent" -gt 80 ] || [ "${mem_percent:-0}" -gt 90 ]; then
return 0 # True - system is under load
fi
@@ -567,7 +567,8 @@ db_has_network_issues() {
# Consider network problematic if retrans > 5% or errors > 100
if [ -n "$tcp_retrans" ]; then
if (( $(echo "$tcp_retrans > 5" | bc -l 2>/dev/null || echo 0) )) || \
local retrans_high=$(awk "BEGIN {print ($tcp_retrans > 5 ? 1 : 0)}" 2>/dev/null || echo 0)
if [ "$retrans_high" -eq 1 ] || \
[ "${rx_errors:-0}" -gt 100 ] || [ "${tx_errors:-0}" -gt 100 ]; then
return 0 # True - network has issues
fi
+1 -1
View File
@@ -307,7 +307,7 @@ is_server_stressed() {
load1=$(echo "$load1" | awk '{print $1}')
# Convert to integer (multiply by 100 to handle decimals)
local load_int=$(echo "$load1 * 100" | bc 2>/dev/null | cut -d. -f1)
local load_int=$(awk "BEGIN {printf \"%.0f\", $load1 * 100}" 2>/dev/null)
local threshold=$((cpu_count * 80)) # 80% of CPU count
if [ "$load_int" -gt "$threshold" ]; then
+26 -14
View File
@@ -342,25 +342,32 @@ analyze_cpu() {
local load_15min=$(uptime | awk -F'load average:' '{print $2}' | awk -F',' '{print $3}' | xargs)
# Calculate load per core
local load_per_core=$(echo "$load_1min / $cpu_cores" | bc -l 2>/dev/null | awk '{printf "%.2f", $0}' || echo "0")
local load_per_core=$(awk "BEGIN {printf \"%.2f\", $load_1min / $cpu_cores}" 2>/dev/null || echo "0")
# Calculate healthy load thresholds
local healthy_load=$(echo "$cpu_cores * 0.7" | bc -l | awk '{printf "%.1f", $0}')
local warning_load=$(echo "$cpu_cores * 1.0" | bc -l | awk '{printf "%.1f", $0}')
local critical_load=$(echo "$cpu_cores * 2.0" | bc -l | awk '{printf "%.1f", $0}')
local healthy_load=$(awk "BEGIN {printf \"%.1f\", $cpu_cores * 0.7}")
local warning_load=$(awk "BEGIN {printf \"%.1f\", $cpu_cores * 1.0}")
local critical_load=$(awk "BEGIN {printf \"%.1f\", $cpu_cores * 2.0}")
# Detect load trend (increasing, stable, decreasing)
local load_trend="stable"
if (( $(echo "$load_1min > $load_5min * 1.2" | bc -l) )); then
local trend_rapid=$(awk "BEGIN {print ($load_1min > $load_5min * 1.2 ? 1 : 0)}" 2>/dev/null || echo 0)
local trend_up=$(awk "BEGIN {print ($load_1min > $load_5min ? 1 : 0)}" 2>/dev/null || echo 0)
local trend_down=$(awk "BEGIN {print ($load_1min < $load_5min * 0.8 ? 1 : 0)}" 2>/dev/null || echo 0)
if [ "$trend_rapid" -eq 1 ]; then
load_trend="increasing rapidly"
elif (( $(echo "$load_1min > $load_5min" | bc -l) )); then
elif [ "$trend_up" -eq 1 ]; then
load_trend="increasing"
elif (( $(echo "$load_1min < $load_5min * 0.8" | bc -l) )); then
elif [ "$trend_down" -eq 1 ]; then
load_trend="decreasing"
fi
# Check load average with intelligent thresholds
if (( $(echo "$load_1min > $critical_load" | bc -l) )); then
local load_critical=$(awk "BEGIN {print ($load_1min > $critical_load ? 1 : 0)}" 2>/dev/null || echo 0)
local load_warning=$(awk "BEGIN {print ($load_1min > $warning_load ? 1 : 0)}" 2>/dev/null || echo 0)
if [ "$load_critical" -eq 1 ]; then
local top_cpu=$(ps aux --sort=-%cpu | head -6 | tail -5 | awk '{printf " • %-15s %6s %s\n", $1, $3"%", $11}')
add_issue "CRITICAL" "CPU - Extreme load" \
"Load average: ${load_1min} / ${load_5min} / ${load_15min}
@@ -379,7 +386,7 @@ ${top_cpu}" \
2. Kill if necessary: kill -9 [PID]
3. Check if under attack: Main Menu → Security → Bot Analyzer" \
92
elif (( $(echo "$load_1min > $warning_load" | bc -l) )); then
elif [ "$load_warning" -eq 1 ]; then
local top_cpu=$(ps aux --sort=-%cpu | head -4 | tail -3 | awk '{printf " • %-15s %6s %s\n", $1, $3"%", $11}')
add_issue "HIGH" "CPU - High load" \
"Load average: ${load_1min} / ${load_5min} / ${load_15min}
@@ -396,7 +403,9 @@ ${top_cpu}" \
• Check: ps aux --sort=-%cpu | head -20
• Review high-CPU processes and optimize if possible" \
76
elif (( $(echo "$load_1min > $healthy_load" | bc -l) )); then
else
local load_elevated=$(awk "BEGIN {print ($load_1min > $healthy_load ? 1 : 0)}" 2>/dev/null || echo 0)
if [ "$load_elevated" -eq 1 ]; then
add_issue "MEDIUM" "CPU - Elevated load" \
"Load average: ${load_1min} / ${load_5min} / ${load_15min}
Healthy threshold: < ${healthy_load}
@@ -404,6 +413,7 @@ Trend: ${load_trend}" \
"Monitor trends. Load is elevated but not critical yet." \
62
fi
fi
# Get top CPU consumers
ps aux --sort=-%cpu | head -11 | tail -10 > "$TEMP_DIR/top_cpu.txt"
@@ -818,8 +828,9 @@ New connections may be dropped" \
tcp_out=$(echo "$tcp_out" | tr -d '\n\r' | grep -o '[0-9]*' | head -1)
tcp_out=${tcp_out:-1}
if [ "$tcp_out" -gt 1000000 ] 2>/dev/null; then
local retrans_percent=$(echo "scale=2; $tcp_retrans * 100 / $tcp_out" | bc 2>/dev/null || echo "0")
if (( $(echo "$retrans_percent > 5" | bc -l 2>/dev/null) )); then
local retrans_percent=$(awk "BEGIN {printf \"%.2f\", $tcp_retrans * 100 / $tcp_out}" 2>/dev/null || echo "0")
local retrans_high=$(awk "BEGIN {print ($retrans_percent > 5 ? 1 : 0)}" 2>/dev/null || echo 0)
if [ "$retrans_high" -eq 1 ]; then
# Get current MTU
local current_mtu=$(ip link show $(ip route | grep default | awk '{print $5}' | head -1) 2>/dev/null | grep mtu | awk '{print $5}')
@@ -891,7 +902,8 @@ Time drift can cause SSL certificate errors and authentication issues" \
# Convert to absolute value for comparison
offset_seconds=${offset_seconds#-}
if (( $(echo "$offset_seconds > 1" | bc -l 2>/dev/null || echo "0") )); then
local offset_high=$(awk "BEGIN {print ($offset_seconds > 1 ? 1 : 0)}" 2>/dev/null || echo 0)
if [ "$offset_high" -eq 1 ]; then
add_issue "HIGH" "TIME - Clock offset detected" \
"Time offset: ${sync_status}
Significant time drift detected" \
@@ -1682,7 +1694,7 @@ save_health_baseline() {
tcp_out=${tcp_out:-1}
local tcp_retrans_percent="0"
if [ "$tcp_out" -gt 1000000 ] 2>/dev/null; then
tcp_retrans_percent=$(echo "scale=2; $tcp_retrans * 100 / $tcp_out" | bc 2>/dev/null || echo "0")
tcp_retrans_percent=$(awk "BEGIN {printf \"%.2f\", $tcp_retrans * 100 / $tcp_out}" 2>/dev/null || echo "0")
fi
local rx_errors=0
+1 -1
View File
@@ -261,7 +261,7 @@ check_cpu_health() {
local cpu_freq=""
if [ -f "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" ]; then
local freq_khz=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq)
cpu_freq=$(echo "scale=2; $freq_khz / 1000000" | bc)" GHz"
cpu_freq=$(awk "BEGIN {printf \"%.2f\", $freq_khz / 1000000}")" GHz"
fi
# Check CPU temperature if sensors available
@@ -165,7 +165,8 @@ Total: $current_month_total" \
local today_unit=$(echo "$today_total" | awk '{print $2}')
if [ "$today_unit" = "GiB" ] && [ -n "$today_value" ]; then
if (( $(echo "$today_value > 50" | bc -l 2>/dev/null || echo 0) )); then
local high_usage=$(awk "BEGIN {print ($today_value > 50 ? 1 : 0)}" 2>/dev/null || echo 0)
if [ "$high_usage" -eq 1 ]; then
add_finding "WARNING" "High Daily Bandwidth Usage" \
"Today's usage: $today_total
This is significantly higher than typical usage" \
@@ -234,7 +235,7 @@ analyze_web_traffic() {
local bytes=$(awk '{sum+=$10} END {print sum}' "$logfile" 2>/dev/null || echo "0")
if [ "$bytes" -gt 0 ]; then
local mb=$(echo "scale=2; $bytes / 1048576" | bc 2>/dev/null || echo "0")
local mb=$(awk "BEGIN {printf \"%.2f\", $bytes / 1048576}")
domain_bandwidth+="$(printf '%-40s %10.2f MB' "$domain" "$mb")"$'\n'
fi
done
@@ -384,9 +385,10 @@ TX Dropped: $tx_dropped" \
local tcp_out=$(netstat -s 2>/dev/null | grep "segments sent out" | awk '{print $1}' || echo "1")
if [ "$tcp_out" -gt 1000000 ]; then
local retrans_percent=$(echo "scale=2; $tcp_retrans * 100 / $tcp_out" | bc 2>/dev/null || echo "0")
local retrans_percent=$(awk "BEGIN {printf \"%.2f\", $tcp_retrans * 100 / $tcp_out}")
local retrans_high=$(awk "BEGIN {print ($retrans_percent > 5 ? 1 : 0)}" 2>/dev/null || echo 0)
if (( $(echo "$retrans_percent > 5" | bc -l 2>/dev/null || echo 0) )); then
if [ "$retrans_high" -eq 1 ]; then
add_finding "WARNING" "High TCP Retransmission Rate" \
"Retransmission rate: ${retrans_percent}%
Segments retransmitted: $tcp_retrans
@@ -410,7 +412,8 @@ Total segments sent: $tcp_out" \
local ping_result=$(ping -c 5 -W 2 8.8.8.8 2>/dev/null | grep "packet loss" | awk '{print $6}' | tr -d '%')
if [ -n "$ping_result" ]; then
if (( $(echo "$ping_result > 5" | bc -l 2>/dev/null || echo 0) )); then
local packet_loss_high=$(awk "BEGIN {print ($ping_result > 5 ? 1 : 0)}" 2>/dev/null || echo 0)
if [ "$packet_loss_high" -eq 1 ]; then
add_finding "WARNING" "Packet Loss Detected" \
"Packet loss to 8.8.8.8: ${ping_result}%
This indicates network connectivity issues" \
+6 -2
View File
@@ -454,10 +454,13 @@ optimize_domain() {
if [ "$status" = "DISABLED" ]; then
cecho "${GREEN}2.${NC} ${BOLD}Enable OPcache${NC} for 40-70% performance boost"
echo ""
elif (( $(echo "$hit_rate < 90" | bc -l 2>/dev/null || echo "0") )); then
else
local hit_rate_low=$(awk "BEGIN {print ($hit_rate < 90 ? 1 : 0)}" 2>/dev/null || echo 0)
if [ "$hit_rate_low" -eq 1 ]; then
cecho "${GREEN}2.${NC} ${BOLD}Increase opcache.memory_consumption${NC} (current hit rate: ${hit_rate}%)"
echo ""
fi
fi
echo ""
cecho "${CYAN}─────────────────────────────────────────────────────────────────────${NC}"
@@ -650,7 +653,8 @@ view_opcache_stats() {
# Recommendation
echo ""
if (( $(echo "$hit_rate < 90" | bc -l 2>/dev/null || echo "0") )); then
local hit_rate_low=$(awk "BEGIN {print ($hit_rate < 90 ? 1 : 0)}" 2>/dev/null || echo 0)
if [ "$hit_rate_low" -eq 1 ]; then
cecho " ${YELLOW}⚠ Hit rate below 90% - Consider increasing opcache.memory_consumption${NC}"
else
cecho " ${GREEN}✓ Hit rate is excellent${NC}"
+5 -5
View File
@@ -71,7 +71,7 @@ while IFS=: read -r file line_num line_content; do
echo "CRITICAL|$file|$line_num|grep -F with regex anchor"
count_issue "CRITICAL"
fi
done < <(grep -rn 'grep -F' "$TOOLKIT_PATH" --include="*.sh" 2>/dev/null)
done < <(grep -rn 'grep -F' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null)
echo ""
} >> "$REPORT"
@@ -228,9 +228,9 @@ while IFS=: read -r file line_num line_content; do
echo "LOW|$file|$line_num|Uses bc command"
count_issue "LOW"
fi
done < <(grep -rn ' bc\b' "$TOOLKIT_PATH" --include="*.sh" 2>/dev/null | head -10)
done < <(grep -rn ' bc\b' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | head -10)
total_bc=$(grep -r ' bc\b' "$TOOLKIT_PATH" --include="*.sh" 2>/dev/null | wc -l)
total_bc=$(grep -r ' bc\b' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | wc -l)
echo "Total found: $total_bc (showing first 10)"
echo ""
} >> "$REPORT"
@@ -254,9 +254,9 @@ while IFS=: read -r file line_num line_content; do
count_issue "MEDIUM"
fi
fi
done < <(grep -rn '/var/cpanel' "$TOOLKIT_PATH" --include="*.sh" 2>/dev/null | head -10)
done < <(grep -rn '/var/cpanel' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | head -10)
total_cpanel=$(grep -r '/var/cpanel' "$TOOLKIT_PATH" --include="*.sh" 2>/dev/null | grep -vE '(\$SYS|:-/var/cpanel)' | grep -v '^[[:space:]]*#' | wc -l)
total_cpanel=$(grep -r '/var/cpanel' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | grep -vE '(\$SYS|:-/var/cpanel)' | grep -v '^[[:space:]]*#' | wc -l)
echo "Total found: $total_cpanel (showing first 10)"
echo ""
} >> "$REPORT"