#!/bin/bash # Bitcoin Knots health check — managed by Ansible (roles/bitcoin_knots) # # The exit code is the answer and systemd keeps it: # systemctl is-failed bitcoin-knots-healthcheck.service # Reporting anywhere else is optional and generic. # # RPC_HOST="{{ bitcoin_rpc_bind }}" RPC_PORT={{ bitcoin_rpc_port }} RPC_USER="{{ bitcoin_rpc_user }}" RPC_PASSWORD="{{ bitcoin_rpc_password }}" PUSH_URL="${HEALTHCHECK_PUSH_URL:-}" # Check if bitcoind RPC is responding check_bitcoind() { local response response=$(curl -s --max-time 30 \ --user "${RPC_USER}:${RPC_PASSWORD}" \ --data-binary '{"jsonrpc":"1.0","id":"healthcheck","method":"getblockchaininfo","params":[]}' \ --header 'Content-Type: application/json' \ "http://${RPC_HOST}:${RPC_PORT}" 2>&1) if [ $? -eq 0 ]; then # Check if response contains a non-null error # Successful responses have "error": null, failures have "error": {...} if echo "$response" | grep -q '"error":null\|"error": null'; then return 0 else return 1 fi else return 1 fi } report() { local status=$1 local msg=$2 # No push URL is normal, not an error: the exit code below is still a # complete answer for anything reading unit state. [ -n "$PUSH_URL" ] || return 0 # URL encode spaces in message local encoded_msg="${msg// /%20}" if ! curl -s --max-time 10 --retry 2 -o /dev/null \ "${PUSH_URL}?status=${status}&msg=${encoded_msg}&ping="; then return 1 fi } # Main health check if check_bitcoind; then report "up" "OK" exit 0 else report "down" "bitcoind RPC not responding" exit 1 fi