比特幣節點監控完整指南

深入介紹如何自建比特幣節點的監控系統,涵蓋腳本自動化、警報設定和儀表板建置。

比特幣節點監控完整指南

深入介紹如何自建比特幣節點的監控系統,涵蓋腳本自動化、警報設定和儀表板建置。

監控概述

為何需要監控比特幣節點?

監控項目重要性影響
同步狀態節點可能落後攻擊
連接數網路連接問題
記憶體使用OOM 當機
磁碟空間同步失敗
區塊高度確認交易狀態

基本監控腳本

Shell 監控腳本

節點狀態檢查

#!/bin/bash
# bitcoin-monitor.sh

RPC_USER="your-user"
RPC_PASS="your-password"
RPC_PORT="8332"
HOST="127.0.0.1"

# 顏色定義
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

# 獲取節點資訊
get_info() {
    curl -s -u ${RPC_USER}:${RPC_PASS} \
        -X POST \
        -H "content-type: text/plain;" \
        --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getblockchaininfo", "params": []}' \
        http://${HOST}:${RPC_PORT}/ | jq -r '.result'
}

# 檢查節點狀態
check_status() {
    INFO=$(get_info)

    if [ "$INFO" = "null" ]; then
        echo -e "${RED}✗ 節點無回應${NC}"
        exit 1
    fi

    BLOCKS=$(echo "$INFO" | jq -r '.blocks')
    HEADERS=$(echo "$INFO" | jq -r '.headers')
    SYNCED=$(echo "$INFO" | jq -r '.initialblockdownload')

    echo "=== 比特幣節點狀態 ==="
    echo "區塊高度: $BLOCKS"
    echo "標題數量: $HEADERS"

    if [ "$SYNCED" = "true" ]; then
        echo -e "同步狀態: ${GREEN}已完成${NC}"
    else
        echo -e "同步狀態: ${YELLOW}同步中${NC}"
    fi
}

# 檢查連接數
check_connections() {
    CONNECTIONS=$(curl -s -u ${RPC_USER}:${RPC_PASS} \
        -X POST \
        -H "content-type: text/plain;" \
        --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getconnectioncount", "params": []}' \
        http://${HOST}:${RPC_PORT}/ | jq -r '.result')

    echo "連接數: $CONNECTIONS"

    if [ "$CONNECTIONS" -lt 8 ]; then
        echo -e "${RED}⚠ 連接數過低${NC}"
    fi
}

# 檢查記憶體
check_memory() {
    MEM=$(free -m | grep Mem | awk '{print $3}')
    MEM_TOTAL=$(free -m | grep Mem | awk '{print $2}')
    MEM_PERCENT=$((MEM * 100 / MEM_TOTAL))

    echo "記憶體使用: ${MEM}MB / ${MEM_TOTAL}MB (${MEM_PERCENT}%)"

    if [ "$MEM_PERCENT" -gt 90 ]; then
        echo -e "${RED}⚠ 記憶體使用過高${NC}"
    fi
}

# 檢查磁碟空間
check_disk() {
    DISK=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')

    echo "磁碟使用: ${DISK}%"

    if [ "$DISK" -gt 85 ]; then
        echo -e "${RED}⚠ 磁碟空間不足${NC}"
    fi
}

# 執行所有檢查
check_status
check_connections
check_memory
check_disk

自動化排程

# 編輯 crontab
crontab -e

# 每 5 分鐘執行一次監控
*/5 * * * * /path/to/bitcoin-monitor.sh >> /var/log/bitcoin-monitor.log 2>&1

Python 監控腳本

#!/usr/bin/env python3
# bitcoin_monitor.py

import requests
import json
import time
from datetime import datetime

class BitcoinNodeMonitor:
    def __init__(self, rpc_user, rpc_pass, host='127.0.0.1', port=8332):
        self.url = f"http://{host}:{port}/"
        self.auth = (rpc_user, rpc_pass)
        self.session = requests.Session()
        self.session.auth = self.auth

    def rpc_call(self, method, params=None):
        payload = {
            "jsonrpc": "1.0",
            "id": "monitor",
            "method": method,
            "params": params or []
        }
        response = self.session.post(
            self.url,
            json=payload,
            headers={"content-type": "text/plain"}
        )
        return response.json()["result"]

    def get_blockchain_info(self):
        return self.rpc_call("getblockchaininfo")

    def get_network_info(self):
        return self.rpc_call("getnetworkinfo")

    def get_mempool_info(self):
        return self.rpc_call("getmempoolinfo")

    def check_health(self):
        """完整健康檢查"""
        results = {
            "timestamp": datetime.now().isoformat(),
            "blockchain": self.get_blockchain_info(),
            "network": self.get_network_info(),
            "mempool": self.get_mempool_info()
        }

        # 檢查同步狀態
        if results["blockchain"]["initialblockdownload"]:
            results["status"] = "syncing"
        elif results["blockchain"]["blocks"] == results["blockchain"]["headers"]:
            results["status"] = "synced"
        else:
            results["status"] = "error"

        # 檢查連接數
        results["connections_ok"] = results["network"]["connections"] >= 8

        return results

    def get_peer_info(self):
        return self.rpc_call("getpeerinfo")

    def get_block_stats(self, block_hash_or_height):
        return self.rpc_call("getblockstats", [block_hash_or_height])

if __name__ == "__main__":
    monitor = BitcoinNodeMonitor("rpcuser", "rpcpass")

    health = monitor.check_health()
    print(json.dumps(health, indent=2))

警報系統

Telegram 警報

#!/usr/bin/env python3
# alert_system.py

import requests
import json

class AlertManager:
    def __init__(self, telegram_bot_token, telegram_chat_id):
        self.bot_token = telegram_bot_token
        self.chat_id = telegram_chat_id
        self.api_url = f"https://api.telegram.org/bot{self.bot_token}"

    def send_alert(self, message, parse_mode="Markdown"):
        """發送 Telegram 訊息"""
        url = f"{self.api_url}/sendMessage"
        data = {
            "chat_id": self.chat_id,
            "text": message,
            "parse_mode": parse_mode
        }
        return requests.post(url, json=data).json()

    def send_photo(self, photo_path, caption):
        """發送圖片"""
        url = f"{self.api_url}/sendPhoto"
        files = {"photo": open(photo_path, "rb")}
        data = {"chat_id": self.chat_id, "caption": caption}
        return requests.post(url, files=files, data=data).json()

# 警報範例
def check_and_alert(monitor):
    health = monitor.check_health()

    # 檢查同步狀態
    if health["status"] != "synced":
        alert_mgr = AlertManager("BOT_TOKEN", "CHAT_ID")
        alert_mgr.send_alert(
            f"⚠️ *比特幣節點警報*\n\n"
            f"狀態: {health['status']}\n"
            f"區塊: {health['blockchain']['blocks']}\n"
            f"落後: {health['blockchain']['headers'] - health['blockchain']['blocks']} 區塊"
        )

    # 檢查連接數
    if not health["connections_ok"]:
        alert_mgr = AlertManager("BOT_TOKEN", "CHAT_ID")
        alert_mgr.send_alert(
            f"⚠️ *連接數過低*\n\n"
            f"連接數: {health['network']['connections']}\n"
            f"需要至少 8 個連接"
        )

Email 警報

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

class EmailAlerts:
    def __init__(self, smtp_server, smtp_port, username, password, from_addr):
        self.smtp_server = smtp_server
        self.smtp_port = smtp_port
        self.username = username
        self.password = password
        self.from_addr = from_addr

    def send_email(self, to_addr, subject, body):
        msg = MIMEMultipart()
        msg["From"] = self.from_addr
        msg["To"] = to_addr
        msg["Subject"] = subject

        msg.attach(MIMEText(body, "plain"))

        with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
            server.starttls()
            server.login(self.username, self.password)
            server.send_message(msg)

監控腳本整合

#!/bin/bash
# monitor-with-alerts.sh

RPC_USER="your-user"
RPC_PASS="your-password"

LOG_FILE="/var/log/bitcoin-monitor.log"
ALERT_SCRIPT="/path/to/alert_system.py"

# 記錄函數
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

# 檢查節點狀態
CHECK=$(curl -s -u ${RPC_USER}:${RPC_PASS} \
    -X POST \
    -H "content-type: text/plain;" \
    --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getblockchaininfo", "params": []}' \
    http://127.0.0.1:8332/ | jq -r '.result.blocks')

if [ "$CHECK" = "null" ]; then
    log "ERROR: 節點無回應"
    python3 $ALERT_SCRIPT "node_down" "比特幣節點無回應!"
    exit 1
fi

log "OK: 節點正常,高度 $CHECK"

監控儀表板

Prometheus + Grafana

Prometheus 配置

# prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'bitcoin-node'
    static_configs:
      - targets: ['localhost:9100']  # node_exporter
    metrics_path: /metrics

Grafana 儀表板 JSON

{
  "dashboard": {
    "title": "比特幣節點監控",
    "panels": [
      {
        "title": "區塊高度",
        "type": "stat",
        "targets": [
          {
            "expr": "bitcoin_blocks"
          }
        ]
      },
      {
        "title": "連接數",
        "type": "graph",
        "targets": [
          {
            "expr": "bitcoin_connections"
          }
        ]
      },
      {
        "title": "記憶體使用",
        "type": "gauge",
        "targets": [
          {
            "expr": "bitcoin_memory_percent"
          }
        ]
      }
    ]
  }
}

開源監控工具

工具用途優點
Prometheus指標收集功能強大
Grafana視覺化靈活儀表板
Netdata即時監控易於部署
Zabbix企業級監控完整功能

進階監控指標

節點健康指標

def calculate_node_score(health):
    """計算節點健康分數"""
    score = 100

    # 同步狀態扣分
    if health["status"] != "synced":
        score -= 30

    # 連接數扣分
    connections = health["network"]["connections"]
    if connections < 8:
        score -= 20
    elif connections < 10:
        score -= 10

    # 記憶體扣分
    mem_percent = health.get("memory_percent", 0)
    if mem_percent > 90:
        score -= 20
    elif mem_percent > 80:
        score -= 10

    # 磁碟扣分
    disk_percent = health.get("disk_percent", 0)
    if disk_percent > 90:
        score -= 20

    return max(0, score)

異常檢測

def detect_anomalies(metrics_history):
    """檢測異常"""
    anomalies = []

    # 檢查區塊高度變化
    if len(metrics_history) > 2:
        recent_blocks = [m["blocks"] for m in metrics_history[-3:]]
        if len(set(recent_blocks)) == 1:
            anomalies.append("區塊高度停滞")

    # 檢查連接數驟降
    if len(metrics_history) > 1:
        prev_conn = metrics_history[-2]["network"]["connections"]
        curr_conn = metrics_history[-1]["network"]["connections"]
        if prev_conn - curr_conn > 5:
            anomalies.append(f"連接數驟降: {prev_conn} -> {curr_conn}")

    return anomalies

自動化維護腳本

磁碟空間管理

#!/bin/bash
# cleanup.sh

# 清理舊區塊(保留最新 100GB)
bitcoin-cli -rpcwallet= pruneblockchain 100000

# 清理日誌
find /var/log -name "bitcoin*.log" -mtime +7 -delete

# 清理調試日誌
rm -rf ~/.bitcoin/logs/*.log

節點重啟腳本

#!/bin/bash
# restart-node.sh

SYSTEMD_SERVICE="bitcoind"

# 檢查服務狀態
if systemctl is-active --quiet $SYSTEMD_SERVICE; then
    echo "節點運行中,重啟中..."
    systemctl restart $SYSTEMD_SERVICE
    sleep 30

    # 驗證重啟成功
    if bitcoin-cli getblockcount > /dev/null 2>&1; then
        echo "節點重啟成功"
    else
        echo "節點重啟失敗,發送警報"
    fi
else
    echo "節點未運行,啟動中..."
    systemctl start $SYSTEMD_SERVICE
fi

常見問題排查

問題:節點落後

解決方案

  1. 檢查網路連接
  2. 增加 maxconnections
  3. 檢查頻寬
  4. 考慮使用更快磁碟

問題:記憶體不足

解決方案

  1. 減少 dbcache
  2. 減少 maxconnections
  3. 使用 swap
  4. 升級硬體

問題:磁碟空間不足

解決方案

  1. 啟用 prune 模式
  2. 清理舊區塊
  3. 遷移到更大磁碟

總結

比特幣節點監控是確保網路安全和服務穩定的關鍵。透過本文介紹的工具和腳本,您可以:

相關連結

延伸閱讀與來源

這篇文章對您有幫助嗎?

評論

發表評論

注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。

目前尚無評論,成為第一個發表評論的人吧!