From 68c01ceafb1baf6a89a5a49cf11a1422d111e24d Mon Sep 17 00:00:00 2001 From: Semaphore Date: Thu, 12 Mar 2026 12:02:16 -0700 Subject: [PATCH] =?UTF-8?q?Fix=20deploy=5Fagent.sh=20=E2=80=94=20stdin=20c?= =?UTF-8?q?onsumption=20in=20loop,=20base64=20script=20delivery=20via=20su?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/deploy_agent.sh | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/scripts/deploy_agent.sh b/scripts/deploy_agent.sh index 0ec9738..f890d92 100755 --- a/scripts/deploy_agent.sh +++ b/scripts/deploy_agent.sh @@ -366,6 +366,12 @@ fi log_section "Processing Linux hosts" +# Write host list to temp file to prevent ssh/sshpass from consuming +# the while loop's stdin (classic bash gotcha with network commands in loops) +LINUX_HOSTS_FILE=$(mktemp) +echo "$LINUX_HOSTS" > "$LINUX_HOSTS_FILE" +trap 'rm -f "$LINUX_HOSTS_FILE"' EXIT + while IFS='|' read -r HOSTNAME HOST_IP; do [[ -z "$HOSTNAME" ]] && continue ((HOSTS_TOTAL++)) || true @@ -379,16 +385,16 @@ while IFS='|' read -r HOSTNAME HOST_IP; do continue fi - # Add host to known_hosts + # Add host to known_hosts — redirect stdin from /dev/null to prevent draining loop fd log_info "Scanning host key..." - ssh-keyscan -T 10 "$HOST_IP" >> /root/.ssh/known_hosts 2>/dev/null || true + ssh-keyscan -T 10 "$HOST_IP" >> /root/.ssh/known_hosts 2>/dev/null < /dev/null || true # Test native user SSH access log_info "Testing SSH as $NATIVE_USER..." if ! sshpass -p "$NATIVE_PASS" ssh -o StrictHostKeyChecking=no \ -o ConnectTimeout=10 \ -o PasswordAuthentication=yes \ - "$NATIVE_USER@$HOST_IP" "echo connected" &>/dev/null; then + "$NATIVE_USER@$HOST_IP" "echo connected" < /dev/null &>/dev/null; then log_error "Cannot SSH to $HOSTNAME ($HOST_IP) as $NATIVE_USER — skipping" FAILED_HOSTS+=("$HOSTNAME ($HOST_IP) — SSH connection failed") ((HOSTS_FAILED++)) || true @@ -403,6 +409,10 @@ while IFS='|' read -r HOSTNAME HOST_IP; do "$AGENT_USER" \ "$SKIP_SSHD") + # Base64-encode the script so it can be passed cleanly through su - root -c + # su -c replaces stdin so 'bash -s' heredoc approach doesn't work + REMOTE_SCRIPT_B64=$(echo "$REMOTE_SCRIPT" | base64 -w 0) + # Execute via su - on remote host log_info "Executing bootstrap via su - root..." BOOTSTRAP_OUTPUT=$(sshpass -p "$NATIVE_PASS" ssh \ @@ -410,7 +420,8 @@ while IFS='|' read -r HOSTNAME HOST_IP; do -o ConnectTimeout=10 \ -o PasswordAuthentication=yes \ "$NATIVE_USER@$HOST_IP" \ - "echo '$ROOT_PASS' | su - root -c 'bash -s'" <<< "$REMOTE_SCRIPT" 2>&1) || { + "echo '$ROOT_PASS' | su - root -c 'echo $REMOTE_SCRIPT_B64 | base64 -d | bash'" \ + < /dev/null 2>&1) || { log_error "Bootstrap script failed on $HOSTNAME" echo "$BOOTSTRAP_OUTPUT" | sed 's/^/ /' FAILED_HOSTS+=("$HOSTNAME ($HOST_IP) — bootstrap script failed") @@ -429,7 +440,8 @@ while IFS='|' read -r HOSTNAME HOST_IP; do -o StrictHostKeyChecking=no \ -o ConnectTimeout=10 \ -o PasswordAuthentication=no \ - "$AGENT_USER@$HOST_IP" "echo key-auth-ok" &>/dev/null; then + "$AGENT_USER@$HOST_IP" "echo key-auth-ok" \ + < /dev/null &>/dev/null; then log_ok "Key-based login verified for $AGENT_USER" else log_warn "Key-based login test failed for $AGENT_USER — check manually" @@ -441,7 +453,7 @@ while IFS='|' read -r HOSTNAME HOST_IP; do log_ok "Bootstrap complete: $HOSTNAME" ((HOSTS_OK++)) || true -done <<< "$LINUX_HOSTS" +done < "$LINUX_HOSTS_FILE" # ─── Summary ───────────────────────────────────────────────────────────────── echo "" @@ -466,4 +478,3 @@ echo "" if [[ $HOSTS_FAILED -gt 0 ]]; then exit 1 fi -