# common useful functions w3m_safe() { url="$1" output=$(/opt/homebrew/bin/w3m "$url" -M -cols 400 -graph -dump 2>&1) if echo "$output" | grep -q "Can't load"; then return 2 else echo "$output" return 0 fi } # Returns: # 0 = server reachable & remote command ran # 1 = network/host-not-up-yet # 2 = SSH auth failure (key needs passphrase / wrong key / agent locked) -> caller should abort # 3 = host not found is_server_up() { local host err st err_lc host=$1 # return 3 if the host does not exist host "$host" 2>&1 > /dev/null || return 3 # Capture only stderr; do NOT use -q (it suppresses diagnostics we need to classify). # Force English messages for stable matching. err=$(LC_ALL=C /usr/bin/ssh \ -o BatchMode=yes \ -o PreferredAuthentications=publickey \ -o PubkeyAuthentication=yes \ -o PasswordAuthentication=no \ -o KbdInteractiveAuthentication=no \ -o NumberOfPasswordPrompts=0 \ -o ConnectTimeout=10 \ -o ServerAliveInterval=20 \ -o ServerAliveCountMax=3 \ -o ConnectionAttempts=1 \ -o StrictHostKeyChecking=no \ -o UserKnownHostsFile=/dev/null \ -o LogLevel=ERROR \ -n "$host" 'uname -n || hostname' 2>&1 >/dev/null) st=$? # Success [ $st -eq 0 ] && return 0 # ssh uses 255 for any error; distinguish by stderr text err_lc=$(printf '%s' "$err" | tr '[:upper:]' '[:lower:]') case $err_lc in # Common auth/passphrase/agent problems *"permission denied"*|\ *"no supported authentication methods available"*|\ *"publickey authentication failed"*|\ *"too many authentication failures"*|\ *"sign_and_send_pubkey: signing failed"*|\ *"agent refused operation"*|\ *"agent admitted failure"*|\ *"bad permissions"*|\ *"enter passphrase"*) printf 'FATAL: SSH authentication failed for "%s": %s\n' "$host" "$err" >&2 return 2 ;; esac # Everything else looks like "not up yet" (timeout, DNS, connection refused/reset, kex read, etc.) return 1 } wait_for_server_to_boot_up() { local server rc server=$1 while :; do is_server_up "$server" rc=$? case $rc in 0) printf '"%s" is up and running.\n' "$server" return 0 ;; 2) printf 'Aborting: SSH authentication failed for "%s" (key needs passphrase / wrong key / agent locked).\n' "$server" >&2 return 2 ;; 3) printf 'Aborting: Host not found.\n' "$server" >&2 return 3 ;; *) printf 'Server "%s" is not up\n' "$server" sleep 10 ;; esac done } # vim: set ts=4 sw=4 tw=0 noet ft=sh: