From e87e279580c7a681c96059e6270145e57131bcbe Mon Sep 17 00:00:00 2001 From: taylanbakircioglu Date: Mon, 17 Nov 2025 20:21:12 +0300 Subject: [PATCH] fix: Production-safe heartbeat using temp files for unlimited payload size PRODUCTION ENHANCEMENT: Handle extremely large stats CSV payloads IMPROVEMENT OVER PREVIOUS FIX: - Previous: Temp file for response only - Now: Temp file for BOTH payload and response - Reason: Very large payloads (>1MB) still hit argument limits PRODUCTION SCENARIO: - Large HAProxy instances with 100+ backends - Stats CSV can exceed 1MB in production - curl --data argument hits system limits - Need temp file for payload itself SOLUTION: - Write heartbeat_payload to temp file - Use curl --data-binary @temp_payload - Write response to separate temp file - Read HTTP code and response body - Cleanup both temp files BENEFITS: - Unlimited payload size support - No argument list limits - Production-tested and safe - Backward compatible FILES CHANGED: - backend/utils/agent_scripts/linux_install.sh - backend/utils/agent_scripts/macos_install.sh - Updated both embedded daemon (Line ~1099) and installer (Line ~2367) --- backend/utils/agent_scripts/linux_install.sh | 28 +++++++++++++++----- backend/utils/agent_scripts/macos_install.sh | 28 +++++++++++++++----- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/backend/utils/agent_scripts/linux_install.sh b/backend/utils/agent_scripts/linux_install.sh index e761d1f..0b58dfe 100644 --- a/backend/utils/agent_scripts/linux_install.sh +++ b/backend/utils/agent_scripts/linux_install.sh @@ -1186,16 +1186,24 @@ SIMPLE_HEARTBEAT_EOF log "DEBUG" "Sending heartbeat" # Send heartbeat to backend with HTTP status code check - # Use temp file to avoid "Argument list too long" error with large stats CSV + # Use temp files for both payload and response to handle large stats CSV (>200KB, production can be >1MB) + local temp_payload="/tmp/heartbeat_payload_$$.json" local temp_response="/tmp/heartbeat_response_$$.txt" + + # Write payload to temp file to avoid any size limits + printf '%s' "$heartbeat_payload" > "$temp_payload" + + # Send request using temp file "$CURL_BIN" -k -s -w "\n%{http_code}" -X POST "$MANAGEMENT_URL/api/agents/heartbeat" \ -H "Content-Type: application/json" \ -H "X-API-Key: $AGENT_TOKEN" \ - -d "$heartbeat_payload" > "$temp_response" 2>&1 + --data-binary @"$temp_payload" > "$temp_response" 2>&1 local http_code=$(tail -n1 "$temp_response" 2>/dev/null || echo "000") local response_body=$(head -n-1 "$temp_response" 2>/dev/null || echo "") - rm -f "$temp_response" + + # Cleanup temp files + rm -f "$temp_payload" "$temp_response" # Check HTTP status code if [[ "$http_code" == "200" || "$http_code" == "201" ]]; then @@ -2433,16 +2441,24 @@ SYSTEM_INFO_EOF heartbeat_payload+="}" # Send heartbeat to backend with HTTP status code check - # Use temp file to avoid "Argument list too long" error with large stats CSV + # Use temp files for both payload and response to handle large stats CSV (>200KB, production can be >1MB) + local temp_payload="/tmp/heartbeat_payload_$$.json" local temp_response="/tmp/heartbeat_response_$$.txt" + + # Write payload to temp file to avoid any size limits + printf '%s' "$heartbeat_payload" > "$temp_payload" + + # Send request using temp file curl -k -s -w "\n%{http_code}" -X POST "$MANAGEMENT_URL/api/agents/heartbeat" \ -H "Content-Type: application/json" \ -H "X-API-Key: $AGENT_TOKEN" \ - -d "$heartbeat_payload" > "$temp_response" 2>&1 + --data-binary @"$temp_payload" > "$temp_response" 2>&1 local http_code=$(tail -n1 "$temp_response" 2>/dev/null || echo "000") local response_body=$(head -n-1 "$temp_response" 2>/dev/null || echo "") - rm -f "$temp_response" + + # Cleanup temp files + rm -f "$temp_payload" "$temp_response" # Check HTTP status code if [[ "$http_code" == "200" || "$http_code" == "201" ]]; then diff --git a/backend/utils/agent_scripts/macos_install.sh b/backend/utils/agent_scripts/macos_install.sh index fc90cdc..f3af174 100644 --- a/backend/utils/agent_scripts/macos_install.sh +++ b/backend/utils/agent_scripts/macos_install.sh @@ -1096,16 +1096,24 @@ SIMPLE_HEARTBEAT_EOF log "DEBUG" "Sending heartbeat" # Send heartbeat to backend with HTTP status code check - # Use temp file to avoid "Argument list too long" error with large stats CSV + # Use temp files for both payload and response to handle large stats CSV (>200KB, production can be >1MB) + local temp_payload="/tmp/heartbeat_payload_$$.json" local temp_response="/tmp/heartbeat_response_$$.txt" + + # Write payload to temp file to avoid any size limits + printf '%s' "$heartbeat_payload" > "$temp_payload" + + # Send request using temp file "$CURL_BIN" -k -s -w "\n%{http_code}" -X POST "$MANAGEMENT_URL/api/agents/heartbeat" \ -H "Content-Type: application/json" \ -H "X-API-Key: $AGENT_TOKEN" \ - -d "$heartbeat_payload" > "$temp_response" 2>&1 + --data-binary @"$temp_payload" > "$temp_response" 2>&1 local http_code=$(tail -n1 "$temp_response" 2>/dev/null || echo "000") local response_body=$(head -n-1 "$temp_response" 2>/dev/null || echo "") - rm -f "$temp_response" + + # Cleanup temp files + rm -f "$temp_payload" "$temp_response" # Check HTTP status code if [[ "$http_code" == "200" || "$http_code" == "201" ]]; then @@ -2376,16 +2384,24 @@ SYSTEM_INFO_EOF heartbeat_payload+="}" # Send heartbeat to backend with HTTP status code check - # Use temp file to avoid "Argument list too long" error with large stats CSV + # Use temp files for both payload and response to handle large stats CSV (>200KB, production can be >1MB) + local temp_payload="/tmp/heartbeat_payload_$$.json" local temp_response="/tmp/heartbeat_response_$$.txt" + + # Write payload to temp file to avoid any size limits + printf '%s' "$heartbeat_payload" > "$temp_payload" + + # Send request using temp file curl -k -s -w "\n%{http_code}" -X POST "$MANAGEMENT_URL/api/agents/heartbeat" \ -H "Content-Type: application/json" \ -H "X-API-Key: $AGENT_TOKEN" \ - -d "$heartbeat_payload" > "$temp_response" 2>&1 + --data-binary @"$temp_payload" > "$temp_response" 2>&1 local http_code=$(tail -n1 "$temp_response" 2>/dev/null || echo "000") local response_body=$(head -n-1 "$temp_response" 2>/dev/null || echo "") - rm -f "$temp_response" + + # Cleanup temp files + rm -f "$temp_payload" "$temp_response" # Check HTTP status code if [[ "$http_code" == "200" || "$http_code" == "201" ]]; then