anchorage_layer_simple/data/restart-services-cron.sh
ncantu e0ce7a9d83 Optimize sync-utxos RPC calls and document bitcoind crash issues
**Motivations:**
- Prevent bitcoind crashes caused by heavy RPC calls without timeout
- Document bitcoind crash and wallet loading stuck issues
- Clean up obsolete files (configure-nginx-proxy.sh, userwallet components, website-skeleton, old fixKnowledge docs)

**Root causes:**
- RPC calls without timeout causing bitcoind crashes
- No pre-check of bitcoind health before heavy operations
- Large wallet (315MB) causing long loading times and potential hangs
- Missing retry mechanism for transient errors

**Correctifs:**
- Add timeouts on RPC calls (5 minutes for listunspent, 10 seconds for healthcheck)
- Add bitcoind health check before synchronization
- Implement retry with exponential backoff
- Reduce maximumCount limit from 9999999 to 500000 UTXOs
- Improve cron script with pre-checks and better error handling
- Add container status verification before script execution

**Evolutions:**
- New check-services-status.sh script for service diagnostics
- Documentation of crash issues in fixKnowledge
- Improved logging with timestamps
- Better error messages and handling

**Pages affectées:**
- data/sync-utxos-spent-status.mjs
- data/sync-utxos-cron.sh
- data/restart-services-cron.sh
- data/check-services-status.sh (new)
- fixKnowledge/sync-utxos-rpc-optimization.md (new)
- fixKnowledge/signet-bitcoind-crash-mining-stopped.md (new)
- fixKnowledge/signet-bitcoind-crash-wallet-loading-stuck.md (new)
- Removed obsolete files: configure-nginx-proxy.sh, userwallet components, website-skeleton files, old fixKnowledge docs

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 08:18:26 +01:00

143 lines
4.8 KiB
Bash
Executable File

#!/bin/bash
# Daily restart of project systemd services (local only).
# Run via cron. Requires passwordless sudo for systemctl restart.
# Log: data/restart-services.log
#
# Local only: no SSH, no remote commands. Manages systemd units and
# local Docker (mempool stack, bitcoind container) on the current machine.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
LOG_FILE="$SCRIPT_DIR/restart-services.log"
MEMPOOL_COMPOSE="${PROJECT_DIR}/mempool/docker-compose.signet.yml"
BITCOIND_CONTAINER="bitcoin-signet-instance"
SERVICES=(
bitcoin-signet
bitcoin
anchorage-api
api-relay
clamav-api
faucet-api
filigrane-api
signet-dashboard
userwallet
website-skeleton
)
log() { echo "$(date -Iseconds) $*" | tee -a "$LOG_FILE"; }
cd "$PROJECT_DIR" || exit 1
log "=== Restart services cron (local only, no SSH) ==="
# 1. Verify enabled (warn if not)
for u in "${SERVICES[@]}"; do
if ! systemctl is-enabled "$u" &>/dev/null; then
log "WARN: $u is not enabled (will not start at boot)"
fi
done
# 2. Restart active units; track attempted
restarted=()
for u in "${SERVICES[@]}"; do
if ! systemctl is-active --quiet "$u" 2>/dev/null; then
log "SKIP: $u not active (not installed or not running on this machine)"
continue
fi
log "Restarting $u..."
if sudo systemctl restart "$u"; then
log " $u OK"
restarted+=("$u")
else
log " $u FAILED"
restarted+=("$u")
fi
done
# 3. Verify active for restarted units
for u in "${restarted[@]}"; do
if ! systemctl is-active --quiet "$u" 2>/dev/null; then
log "WARN: $u not active after restart"
fi
done
# 4. Docker: bitcoind container (local only) - START FIRST
# Bitcoind must be running before mempool can connect to it
if docker ps -a -q -f "name=^${BITCOIND_CONTAINER}$" 2>/dev/null | grep -q .; then
log "Starting/restarting $BITCOIND_CONTAINER..."
bitcoind_ok=0
if docker ps -q -f "name=^${BITCOIND_CONTAINER}$" 2>/dev/null | grep -q .; then
# Container is running, just restart it
if docker restart "$BITCOIND_CONTAINER" &>/dev/null; then
bitcoind_ok=1
fi
else
# Container exists but is stopped, start it
if docker start "$BITCOIND_CONTAINER" &>/dev/null; then
bitcoind_ok=1
fi
fi
if [ "$bitcoind_ok" -eq 1 ]; then
log " $BITCOIND_CONTAINER started, waiting for RPC to be ready..."
# Wait for bitcoind RPC to be ready (max 300 seconds = 5 minutes)
# Increased timeout to handle large wallet loading (e.g., 315MB wallet can take several minutes)
max_wait=300
wait_count=0
while [ $wait_count -lt $max_wait ]; do
BITCOIN_DATADIR=$(docker exec "$BITCOIND_CONTAINER" printenv BITCOIN_DIR 2>/dev/null || echo "/root/.bitcoin")
RPC_RESPONSE=$(docker exec "$BITCOIND_CONTAINER" bitcoin-cli -datadir="$BITCOIN_DATADIR" getblockchaininfo 2>&1)
if echo "$RPC_RESPONSE" | grep -q '"chain"'; then
log " $BITCOIND_CONTAINER RPC ready after ${wait_count}s"
break
elif echo "$RPC_RESPONSE" | grep -q "Loading wallet"; then
# Wallet is still loading, continue waiting
if [ $((wait_count % 30)) -eq 0 ]; then
log " Wallet still loading... (${wait_count}s elapsed)"
fi
elif echo "$RPC_RESPONSE" | grep -q "Could not connect"; then
# Bitcoind not started yet, continue waiting
if [ $((wait_count % 30)) -eq 0 ]; then
log " Bitcoind starting... (${wait_count}s elapsed)"
fi
fi
sleep 2
wait_count=$((wait_count + 2))
done
if [ $wait_count -ge $max_wait ]; then
log " WARN: $BITCOIND_CONTAINER RPC not ready after ${max_wait}s (wallet may still be loading)"
log " Check with: docker exec $BITCOIND_CONTAINER bitcoin-cli -datadir=$BITCOIN_DATADIR getblockchaininfo"
fi
else
log " $BITCOIND_CONTAINER FAILED"
fi
else
log "SKIP: $BITCOIND_CONTAINER container not found (bitcoind may run as systemd)"
fi
# 5. Docker: mempool stack (local only) - START AFTER BITCOIND
# Mempool depends on bitcoind being ready
if [ -f "$MEMPOOL_COMPOSE" ] && command -v docker &>/dev/null; then
log "Starting/restarting mempool (docker)..."
mem_ok=1
(cd "${PROJECT_DIR}/mempool" && docker compose -f docker-compose.signet.yml up -d &>/dev/null) && mem_ok=0
[ "$mem_ok" -ne 0 ] && (cd "${PROJECT_DIR}/mempool" && docker-compose -f docker-compose.signet.yml up -d &>/dev/null) && mem_ok=0
if [ "$mem_ok" -eq 0 ]; then
log " mempool started"
# Wait a bit for mempool to initialize
sleep 5
else
log " mempool FAILED"
fi
else
if [ ! -f "$MEMPOOL_COMPOSE" ]; then
log "SKIP: mempool compose not found (not deployed on this machine)"
else
log "SKIP: mempool requires docker (not available)"
fi
fi
log "=== Done ==="
tail -n 100 "$LOG_FILE" > "$LOG_FILE.tmp" && mv "$LOG_FILE.tmp" "$LOG_FILE"