#!/bin/bash # command info if [ $# -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "-help" ]; then echo "monitor and troubleshot the bitcoin network" echo "bitcoin.monitor.sh [mainnet|testnet|signet] status" echo "bitcoin.monitor.sh [mainnet|testnet|signet] info" echo "bitcoin.monitor.sh [mainnet|testnet|signet] mempool" echo "bitcoin.monitor.sh [mainnet|testnet|signet] network" echo "bitcoin.monitor.sh [mainnet] peer-kickstart [ipv4|ipv6|tor|i2p|auto]" echo "bitcoin.monitor.sh [mainnet] peer-disconnectall" exit 1 fi # check if started with sudo if [ "$EUID" -ne 0 ]; then echo "error='run as root'" exit 1 fi # set based on network type if [ "$1" == "mainnet" ]; then bitcoincli_alias="/usr/local/bin/bitcoin-cli -datadir=/home/bitcoin/.bitcoin -rpcport=8332" service_alias="bitcoind" elif [ "$1" == "testnet" ]; then bitcoincli_alias="/usr/local/bin/bitcoin-cli -datadir=/home/bitcoin/.bitcoin -rpcport=18332" service_alias="tbitcoind" elif [ "$1" == "signet" ]; then bitcoincli_alias="/usr/local/bin/bitcoin-cli -datadir=/home/bitcoin/.bitcoin -rpcport=38332" service_alias="sbitcoind" else echo "error='not supported net'" exit 1 fi ###################################################### # STATUS # check general status info ###################################################### if [ "$2" = "status" ]; then btc_version=$($bitcoincli_alias -version 2>/dev/null | head -1 | cut -d ' ' -f6) btc_running=$(systemctl status $service_alias 2>/dev/null | grep -c "active (running)") btc_ready="0" btc_online="0" btc_error_short="" btc_error_full="" if [ "${btc_running}" != "0" ]; then btc_running="1" # test connection - record win & fail info randStr=$(echo "$RANDOM") rm /var/cache/raspiblitz/.bitcoind-${randStr}.out 2>/dev/null rm /var/cache/raspiblitz/.bitcoind-${randStr}.error 2>/dev/null touch /var/cache/raspiblitz/.bitcoind-${randStr}.out touch /var/cache/raspiblitz/.bitcoind-${randStr}.error $bitcoincli_alias getnetworkinfo 1>/var/cache/raspiblitz/.bitcoind-${randStr}.out 2>/var/cache/raspiblitz/.bitcoind-${randStr}.error winData=$(cat /var/cache/raspiblitz/.bitcoind-${randStr}.out 2>/dev/null) failData=$(cat /var/cache/raspiblitz/.bitcoind-${randStr}.error 2>/dev/null) rm /var/cache/raspiblitz/.bitcoind-${randStr}.out rm /var/cache/raspiblitz/.bitcoind-${randStr}.error # check for errors if [ "${failData}" != "" ]; then btc_ready="0" btc_error_short=$(echo ${failData/error*:/} | sed 's/[^a-zA-Z0-9 ]//g') btc_error_full=$(echo ${failData} | tr -d "'" | tr -d '"') btc_ready="0" # check results if proof for online else btc_ready="1" connections=$( echo "${winData}" | grep "connections\"" | tr -cd '[[:digit:]]') if [ "${connections}" != "" ] && [ "${connections}" != "0" ]; then btc_online="1" fi fi fi # print results echo "btc_version='${btc_version}'" echo "btc_running='${btc_running}'" echo "btc_ready='${btc_ready}'" echo "btc_online='${btc_online}'" echo "btc_error_short='${btc_error_short}'" echo "btc_error_full='${btc_error_full}'" exit 0 fi ###################################################### # NETWORK ###################################################### if [ "$2" = "network" ]; then # get data btc_running=$(systemctl status $service_alias 2>/dev/null | grep -c "active (running)") getnetworkinfo=$($bitcoincli_alias getnetworkinfo 2>/dev/null) if [ "${getnetworkinfo}" == "" ]; then echo "error='no network data'" exit 1 fi getpeerinfo=$($bitcoincli_alias getpeerinfo 2>/dev/null) if [ "${getpeerinfo}" == "" ]; then echo "error='no peer data'" exit 1 fi # parse data btc_peers=$(echo "${getnetworkinfo}" | grep "connections\"" | tr -cd '[[:digit:]]') btc_address=$(echo ${getnetworkinfo} | jq -r '.localaddresses [0] .address') btc_port=$(echo "${getnetworkinfo}" | jq -r '.localaddresses [0] .port') btc_peers_onion=$(echo "${getpeerinfo}" | grep -c "network\": \"onion") btc_peers_i2p=$(echo "${getpeerinfo}" | grep -c "network\": \"i2p") # print data echo "btc_running='${btc_running}'" echo "btc_peers='${btc_peers}'" echo "btc_peers_onion='${btc_peers_onion}'" echo "btc_peers_i2p='${btc_peers_i2p}'" echo "btc_address='${btc_address}'" echo "btc_port='${btc_port}'" exit 0 fi ###################################################### # INFO ###################################################### if [ "$2" = "info" ]; then # get data blockchaininfo=$($bitcoincli_alias getblockchaininfo 2>/dev/null) if [ "${blockchaininfo}" == "" ]; then echo "error='no data'" exit 1 fi subfolder="" if [ "$1" == "testnet" ]; then subfolder="testnet3/" fi if [ "$1" == "signet" ]; then subfolder="signet/" fi btc_blocks_data_kb=$(sudo du -s /mnt/hdd/bitcoin/${subfolder}blocks 2>/dev/null | cut -f1) if [ "${btc_blocks_data_kb}" == "" ]; then btc_blocks_data_kb="0" fi # print data # parse data btc_blocks_headers=$(echo "${blockchaininfo}" | jq -r '.headers') btc_blocks_verified=$(echo "${blockchaininfo}" | jq -r '.blocks') btc_blocks_behind=$((${btc_blocks_headers} - ${btc_blocks_verified})) btc_sync_initialblockdownload=$(echo "${blockchaininfo}" | jq -r '.initialblockdownload' | grep -c 'true') btc_sync_progress=$(echo "${blockchaininfo}" | jq -r '.verificationprogress') if [[ "${btc_sync_progress}" == *"e-"* ]]; then # is still very small - round up to 0.01% btc_sync_percentage="0.01" elif (( $(awk 'BEGIN { print( '${btc_sync_progress}'<0.99995 ) }') )); then # #3620 prevent displaying 100.00%, although incorrect because of rounding btc_sync_percentage="${btc_sync_progress:2:2}.${btc_sync_progress:4:2}" # remove trailing zero if present (just first one) btc_sync_percentage="${btc_sync_percentage#0}" elif [ "${btc_blocks_headers}" != "" ] && [ "${btc_blocks_headers}" == "${btc_blocks_verified}" ]; then btc_sync_percentage="100.00" else btc_sync_percentage="99.99" fi # determine if synced (tolerate falling 1 block behind) # and be sure that initial blockdownload is done btc_synced=0 if [ "${btc_sync_initialblockdownload}" == "0" ] && [ ${btc_blocks_behind} -lt 2 ]; then btc_synced=1 fi # print data echo "btc_synced='${btc_synced}'" echo "btc_blocks_headers='${btc_blocks_headers}'" echo "btc_blocks_verified='${btc_blocks_verified}'" echo "btc_blocks_behind='${btc_blocks_behind}'" echo "btc_blocks_data_kb='${btc_blocks_data_kb}'" echo "btc_sync_progress='${btc_sync_progress}'" echo "btc_sync_percentage='${btc_sync_percentage//[^0-9\..]/}'" echo "btc_sync_initialblockdownload='${btc_sync_initialblockdownload}'" exit 0 fi ###################################################### # MEMPOOL ###################################################### if [ "$2" = "mempool" ]; then # get data mempoolinfo=$($bitcoincli_alias getmempoolinfo 2>/dev/null) if [ "${mempoolinfo}" == "" ]; then echo "error='no data'" exit 1 fi # parse data btc_mempool_transactions=$(echo "${mempoolinfo}" | jq -r '.size') # print data echo "btc_mempool_transactions=${btc_mempool_transactions}" exit 0 fi ################### # PEER KICK START ################### if [ "$2" = "peer-kickstart" ]; then # check calling only for mainnet if [ "$1" != "mainnet" ]; then echo "error='only available for mainnet yet'" exit 1 fi bitnodesRawData1=$(sudo -u admin cat /home/admin/fallback.bitnodes.nodes) if [ ${#bitnodesRawData1} -lt 100 ]; then echo "error='no valid data from bitnodes.io'" exit 1 fi bitnodesRawData2=$(sudo -u admin cat /home/admin/fallback.bitcoin.nodes) if [ ${#bitnodesRawData2} -lt 100 ]; then echo "error='no valid data from bitcoin core'" exit 1 fi # determine which address to choose addressFormat="$3" # set default to auto if [ "${addressFormat}" == "" ]; then addressFormat="auto" fi # check valid value if [ "${addressFormat}" != "ipv4" ] && [ "${addressFormat}" != "ipv6" ] && [ "${addressFormat}" != "tor" ] && [ "${addressFormat}" != "i2p" ] && [ "${addressFormat}" != "auto" ]; then echo "error='invalid address type'" exit 1 fi # if auto then determine whats running if [ "${addressFormat}" == "auto" ]; then if [ "$(cat /mnt/hdd/raspiblitz.conf | grep -c "^runBehindTor=on")" != "0" ]; then addressFormat="tor" else source <(sudo /home/admin/config.scripts/internet.sh status global) if [ "${ipv6}" == "off" ]; then addressFormat="ipv4" else addressFormat="ipv6" fi fi fi echo "addressFormat='${addressFormat}'" # filter raw data for node addresses based on what kind of connection is running if [ "${addressFormat}" == "tor" ]; then # get Tor nodes (v3) nodeList=$(echo "${bitnodesRawData1}" | grep -o '[0-9a-z]\{32,56\}\.onion') elif [ "${addressFormat}" == "ipv4" ]; then # get IPv4 nodes nodeList=$(echo "${bitnodesRawData1}" | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\:[0-9]\{3,5\}') elif [ "${addressFormat}" == "ipv6" ]; then # get IPv6 nodes nodeList=$(echo "${bitnodesRawData1}" | grep -o '\[.\{5,45\}\]\:[0-9]\{3,5\}') elif [ "${addressFormat}" == "i2p" ]; then # get I2P nodes (only in fallbacklist from bitcoin core) nodeList=$(echo "${bitnodesRawData2}" | grep -o '[0-9,a-z]\{32,64\}\.b32\.i2p\:[0-9]\{1,5\}') else # invalid address echo "error='invalid address format'" exit 1 fi #echo "${nodeList}" nodesAvailable=$(echo "${nodeList}" | wc -l) echo "nodesAvailable=${nodesAvailable}" if [ "${nodesAvailable}" == "0" ]; then echo "error='no nodes available'" exit 1 fi # pick random node from list randomLineNumber=$((1 + RANDOM % ${nodesAvailable})) echo "randomNumber=${randomLineNumber}" nodeAddress=$(echo "${nodeList}" | sed -n "${randomLineNumber}p") if [ "${nodeAddress}" == "" ]; then # if random pick fails pick first line nodeAddress=$(echo "${nodeList}" | sed -n "1p") fi if [ "${nodeAddress}" == "" ]; then echo "error='selecting node from list failed'" exit 1 fi echo "newpeer='${nodeAddress}'" # kick start node with $bitcoincli_alias addnode "${nodeAddress}" "onetry" 1>/dev/null echo "exitcode=$?" exit 0 fi ################### # DISCONNECT ALL PEERS # for testing peer kick-start ################### if [ "$2" = "peer-disconnectall" ]; then # check calling only for mainnet if [ "$1" != "mainnet" ]; then echo "error='only available for mainnet yet'" exit 1 fi # get all peer id and disconnect them $bitcoincli_alias getpeerinfo | grep '"addr": "' | while read line do peerID=$(echo $line | cut -d '"' -f4) echo "# disconnecting peer with ID: ${peerID}" $bitcoincli_alias disconnectnode ${peerID} done echo "#### FINAL PEER INFO FROM BITCOIND" $bitcoincli_alias getpeerinfo exit 0 fi echo "FAIL - Unknown Parameter $2" exit 1