docs: Ledger Live integration, contract deploy learnings, NEXT_STEPS updates
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands - CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround - CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check - NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere - MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates - LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
28
scripts/maintenance/README.md
Normal file
28
scripts/maintenance/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Maintenance Scripts
|
||||
|
||||
**daily-weekly-checks.sh** — Daily (explorer, indexer lag, RPC) and weekly (config API, thin pool, log reminder).
|
||||
**schedule-daily-weekly-cron.sh** — Install cron: daily 08:00, weekly Sun 09:00.
|
||||
|
||||
**check-and-fix-explorer-lag.sh** — Checks RPC vs Blockscout block; if lag > threshold (default 500), runs `fix-explorer-indexer-lag.sh` (restart Blockscout).
|
||||
**schedule-explorer-lag-cron.sh** — Install cron for lag check-and-fix: every 6 hours (0, 6, 12, 18). Log: `logs/explorer-lag-fix.log`. Use `--show` to print the line, `--install` to add to crontab, `--remove` to remove.
|
||||
|
||||
## Optional: Alerting on failures
|
||||
|
||||
The daily/weekly script writes a **metric file** when run (if `MAINTENANCE_METRIC_FILE` is set or default `logs/maintenance-checks.metric`):
|
||||
|
||||
```
|
||||
maintenance_checks_failed 0
|
||||
maintenance_checks_timestamp 1739123456
|
||||
```
|
||||
|
||||
- **Use in cron:** After the check, if `maintenance_checks_failed` > 0, send alert.
|
||||
- **Example wrapper (email on failure):**
|
||||
```bash
|
||||
cd /path/to/proxmox && bash scripts/maintenance/daily-weekly-checks.sh daily >> logs/daily-weekly-checks.log 2>&1
|
||||
FAILED=$(grep '^maintenance_checks_failed' logs/maintenance-checks.metric 2>/dev/null | awk '{print $2}')
|
||||
[ -n "$FAILED" ] && [ "$FAILED" -gt 0 ] && echo "Maintenance checks failed: $FAILED" | mail -s "Explorer/maintenance alert" ops@example.com
|
||||
```
|
||||
- **Slack:** Use a small script that reads the metric file and posts to a webhook when `maintenance_checks_failed` > 0.
|
||||
- **Prometheus/Grafana:** Scrape the metric file or run a node_exporter textfile collector on `logs/maintenance-checks.metric`.
|
||||
|
||||
To disable the metric file, set `MAINTENANCE_METRIC_FILE=` (empty) before running the script.
|
||||
50
scripts/maintenance/check-and-fix-explorer-lag.sh
Normal file
50
scripts/maintenance/check-and-fix-explorer-lag.sh
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
# Check explorer indexer lag; if above threshold, run fix-explorer-indexer-lag.sh (restart Blockscout).
|
||||
# For use from cron. Run from project root. Requires LAN/SSH to r630-02 for the fix.
|
||||
# Usage: bash scripts/maintenance/check-and-fix-explorer-lag.sh
|
||||
# Env: EXPLORER_INDEXER_LAG_THRESHOLD (default 500)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true
|
||||
|
||||
IP_RPC_2201="${RPC_2201:-192.168.11.221}"
|
||||
IP_BLOCKSCOUT="${IP_BLOCKSCOUT:-192.168.11.140}"
|
||||
BLOCKSCOUT_API_PORT="${BLOCKSCOUT_API_PORT:-4000}"
|
||||
EXPLORER_INDEXER_LAG_THRESHOLD="${EXPLORER_INDEXER_LAG_THRESHOLD:-500}"
|
||||
|
||||
get_rpc_block() {
|
||||
local hex
|
||||
hex=$(curl -sf --max-time 10 -X POST -H "Content-Type: application/json" \
|
||||
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
|
||||
"http://${IP_RPC_2201}:8545" 2>/dev/null | sed -n 's/.*"result":"\(0x[0-9a-fA-F]*\)".*/\1/p')
|
||||
[ -n "$hex" ] && echo $((hex)) || true
|
||||
}
|
||||
|
||||
get_explorer_block() {
|
||||
local body block
|
||||
body=$(curl -sf --max-time 10 "http://${IP_BLOCKSCOUT}:${BLOCKSCOUT_API_PORT}/api/v2/stats" 2>/dev/null || true)
|
||||
[ -z "$body" ] && return
|
||||
block=$(echo "$body" | sed -n 's/.*"total_blocks"\s*:\s*"\([0-9]*\)".*/\1/p' | head -1)
|
||||
[ -z "$block" ] && block=$(echo "$body" | sed -n 's/.*"total_blocks"\s*:\s*\([0-9]*\).*/\1/p' | head -1)
|
||||
[ -n "$block" ] && echo "$block"
|
||||
}
|
||||
|
||||
rpc_block=$(get_rpc_block)
|
||||
explorer_block=$(get_explorer_block)
|
||||
|
||||
if [ -z "$rpc_block" ] || [ -z "$explorer_block" ]; then
|
||||
echo "$(date -Iseconds) SKIP (RPC or Blockscout unreachable)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
lag=$((rpc_block - explorer_block))
|
||||
if [ "$lag" -le "${EXPLORER_INDEXER_LAG_THRESHOLD}" ] 2>/dev/null; then
|
||||
echo "$(date -Iseconds) OK lag=$lag (threshold=${EXPLORER_INDEXER_LAG_THRESHOLD})"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "$(date -Iseconds) LAG $lag > ${EXPLORER_INDEXER_LAG_THRESHOLD} — running fix"
|
||||
bash "$PROJECT_ROOT/scripts/fix-explorer-indexer-lag.sh" 2>&1 || true
|
||||
191
scripts/maintenance/daily-weekly-checks.sh
Executable file
191
scripts/maintenance/daily-weekly-checks.sh
Executable file
@@ -0,0 +1,191 @@
|
||||
#!/usr/bin/env bash
|
||||
# Maintenance checks (ALL_IMPROVEMENTS 135–139). Run daily (135–136) or weekly (137–138).
|
||||
# Explorer: hardened to FAIL when API unreachable; indexer lag check (fail if >500 blocks behind).
|
||||
# Usage: ./scripts/maintenance/daily-weekly-checks.sh [daily|weekly|all]
|
||||
# Cron: 0 8 * * * /path/to/daily-weekly-checks.sh daily
|
||||
# Set EXPLORER_FAIL_WHEN_UNREACHABLE=0 to keep legacy SKIP when explorer unreachable (e.g. off-LAN).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true
|
||||
|
||||
MODE="${1:-daily}"
|
||||
|
||||
# Defaults (override via config or env)
|
||||
IP_RPC_2201="${RPC_2201:-192.168.11.221}"
|
||||
IP_BLOCKSCOUT="${IP_BLOCKSCOUT:-192.168.11.140}"
|
||||
BLOCKSCOUT_API_PORT="${BLOCKSCOUT_API_PORT:-4000}"
|
||||
DBIS_API_URL="${DBIS_API_URL:-https://dbis-api.d-bis.org}"
|
||||
PROXMOX_R630_02="${PROXMOX_HOST_R630_02:-192.168.11.12}"
|
||||
# Fail daily run when explorer API unreachable (set 0 to preserve legacy SKIP when off-LAN)
|
||||
EXPLORER_FAIL_WHEN_UNREACHABLE="${EXPLORER_FAIL_WHEN_UNREACHABLE:-1}"
|
||||
# Indexer lag: fail if explorer block is more than this many blocks behind RPC head
|
||||
# Set 1500 temporarily if indexer is catching up after restart (~50 min at 2s/block).
|
||||
EXPLORER_INDEXER_LAG_THRESHOLD="${EXPLORER_INDEXER_LAG_THRESHOLD:-500}"
|
||||
|
||||
# Optional: write metric file for alerting (FAILED count and timestamp)
|
||||
MAINTENANCE_METRIC_FILE="${MAINTENANCE_METRIC_FILE:-$PROJECT_ROOT/logs/maintenance-checks.metric}"
|
||||
|
||||
FAILED=0
|
||||
|
||||
check_rpc() {
|
||||
echo -n "[136] RPC (${IP_RPC_2201}:8545)... "
|
||||
if curl -sf --max-time 10 -X POST -H "Content-Type: application/json" \
|
||||
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
|
||||
"http://${IP_RPC_2201}:8545" | grep -q '"result"'; then
|
||||
echo "OK"
|
||||
else
|
||||
echo "FAIL"
|
||||
((FAILED++)) || true
|
||||
fi
|
||||
}
|
||||
|
||||
# Get RPC chain head block number (decimal). Empty on failure.
|
||||
get_rpc_block_number() {
|
||||
local hex
|
||||
hex=$(curl -sf --max-time 10 -X POST -H "Content-Type: application/json" \
|
||||
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
|
||||
"http://${IP_RPC_2201}:8545" 2>/dev/null | sed -n 's/.*"result":"\(0x[0-9a-fA-F]*\)".*/\1/p')
|
||||
[ -n "$hex" ] && echo $((hex)) || true
|
||||
}
|
||||
|
||||
# Get Blockscout last indexed block (from /api/v2/stats total_blocks or /api/v2/blocks). Empty on failure.
|
||||
get_explorer_block_number() {
|
||||
local body block
|
||||
body=$(curl -sf --max-time 10 "http://${IP_BLOCKSCOUT}:${BLOCKSCOUT_API_PORT}/api/v2/stats" 2>/dev/null || true)
|
||||
if [ -n "$body" ] && echo "$body" | grep -qE '"total_blocks"|"total_transactions"'; then
|
||||
# total_blocks in API v2 can be string or number
|
||||
block=$(echo "$body" | sed -n 's/.*"total_blocks"\s*:\s*"\([0-9]*\)".*/\1/p' | head -1)
|
||||
[ -z "$block" ] && block=$(echo "$body" | sed -n 's/.*"total_blocks"\s*:\s*\([0-9]*\).*/\1/p' | head -1)
|
||||
[ -n "$block" ] && echo "$block" && return
|
||||
fi
|
||||
# Fallback: first block from /api/v2/blocks
|
||||
body=$(curl -sf --max-time 10 "http://${IP_BLOCKSCOUT}:${BLOCKSCOUT_API_PORT}/api/v2/blocks?page_size=1" 2>/dev/null || true)
|
||||
if [ -n "$body" ]; then
|
||||
echo "$body" | sed -n 's/.*"height"\s*:\s*\([0-9]*\).*/\1/p' | head -1
|
||||
fi
|
||||
}
|
||||
|
||||
# [135] Explorer: API must return 200 with total_blocks/total_transactions. FAIL when unreachable if EXPLORER_FAIL_WHEN_UNREACHABLE=1.
|
||||
check_explorer_sync() {
|
||||
echo -n "[135] Explorer indexer (${IP_BLOCKSCOUT}:${BLOCKSCOUT_API_PORT})... "
|
||||
local api_ok=0
|
||||
if curl -sf --max-time 10 "http://${IP_BLOCKSCOUT}:${BLOCKSCOUT_API_PORT}/api/v2/stats" 2>/dev/null | grep -qE '"total_blocks"|"total_transactions"|"indexer"'; then
|
||||
api_ok=1
|
||||
elif curl -sf --max-time 10 "http://${IP_BLOCKSCOUT}:${BLOCKSCOUT_API_PORT}/api?module=stats&action=eth_price" 2>/dev/null | grep -qE '"result"|"eth_price"'; then
|
||||
api_ok=1
|
||||
fi
|
||||
if [ "$api_ok" -eq 1 ]; then
|
||||
echo "OK"
|
||||
return
|
||||
fi
|
||||
# Try public URL (in case we're off-LAN and only NPMplus path works)
|
||||
if curl -sf --max-time 10 -k "https://explorer.d-bis.org/api/v2/stats" 2>/dev/null | grep -qE '"total_blocks"|"total_transactions"'; then
|
||||
echo "OK (public)"
|
||||
return
|
||||
fi
|
||||
if [ "${EXPLORER_FAIL_WHEN_UNREACHABLE}" = "1" ]; then
|
||||
echo "FAIL (Blockscout unreachable)"
|
||||
((FAILED++)) || true
|
||||
else
|
||||
echo "SKIP (Blockscout unreachable; run from LAN or set EXPLORER_FAIL_WHEN_UNREACHABLE=1)"
|
||||
fi
|
||||
}
|
||||
|
||||
# [135b] Indexer lag: fail if explorer block is more than EXPLORER_INDEXER_LAG_THRESHOLD behind RPC head.
|
||||
check_explorer_indexer_lag() {
|
||||
echo -n "[135b] Explorer indexer lag (RPC vs Blockscout)... "
|
||||
local rpc_block explorer_block lag
|
||||
rpc_block=$(get_rpc_block_number)
|
||||
explorer_block=$(get_explorer_block_number)
|
||||
if [ -z "$rpc_block" ] || [ -z "$explorer_block" ]; then
|
||||
echo "SKIP (RPC or Blockscout unreachable)"
|
||||
return
|
||||
fi
|
||||
if [ "$rpc_block" -gt "$explorer_block" ] 2>/dev/null; then
|
||||
lag=$((rpc_block - explorer_block))
|
||||
if [ "$lag" -gt "${EXPLORER_INDEXER_LAG_THRESHOLD}" ]; then
|
||||
echo "FAIL (lag ${lag} > ${EXPLORER_INDEXER_LAG_THRESHOLD})"
|
||||
((FAILED++)) || true
|
||||
else
|
||||
echo "OK (lag ${lag})"
|
||||
fi
|
||||
else
|
||||
echo "OK (explorer caught up)"
|
||||
fi
|
||||
}
|
||||
|
||||
check_config_api() {
|
||||
echo -n "[137] Config API (${DBIS_API_URL})... "
|
||||
if curl -sf --max-time 10 -o /dev/null -w "%{http_code}" "${DBIS_API_URL}/health" 2>/dev/null | grep -q 200; then
|
||||
echo "OK"
|
||||
else
|
||||
echo "SKIP or FAIL (external URL; may be unreachable off-LAN)"
|
||||
fi
|
||||
}
|
||||
|
||||
# [138a] Weekly: thin pool usage on r630-02 (VMID 5000 host). Warn >85%, fail at 100%.
|
||||
check_thin_pool_r630_02() {
|
||||
echo -n "[138a] Thin pool r630-02 (thin1/thin5)... "
|
||||
local out usage pct
|
||||
out=$(ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no root@"${PROXMOX_R630_02}" "pvesm status 2>/dev/null | grep -E 'thin1|thin5' || true" 2>/dev/null || true)
|
||||
if [ -z "$out" ]; then
|
||||
echo "SKIP (SSH to ${PROXMOX_R630_02} failed or no thin pool)"
|
||||
return
|
||||
fi
|
||||
# pvesm status: name, type, status, ... sometimes usage % in output; try to get numeric usage
|
||||
if echo "$out" | grep -q '100%'; then
|
||||
echo "FAIL (thin pool 100% full)"
|
||||
((FAILED++)) || true
|
||||
return
|
||||
fi
|
||||
# Check for high usage (e.g. 85% or more) - common format has percent in line
|
||||
pct=$(echo "$out" | sed -n 's/.*\([0-9]\{2,3\}\)%.*/\1/p' | head -1)
|
||||
if [ -n "$pct" ] && [ "$pct" -ge 85 ] 2>/dev/null; then
|
||||
echo "WARN (usage ${pct}% >= 85%)"
|
||||
# Optional: increment FAILED only at 100%; for now just warn at 85%
|
||||
else
|
||||
echo "OK"
|
||||
fi
|
||||
}
|
||||
|
||||
# Write metric file for alerting (FAILED count, timestamp). Optional.
|
||||
write_metric_file() {
|
||||
[ -z "${MAINTENANCE_METRIC_FILE}" ] && return
|
||||
mkdir -p "$(dirname "$MAINTENANCE_METRIC_FILE")"
|
||||
echo "maintenance_checks_failed ${FAILED}" > "${MAINTENANCE_METRIC_FILE}.$$"
|
||||
echo "maintenance_checks_timestamp $(date +%s)" >> "${MAINTENANCE_METRIC_FILE}.$$"
|
||||
mv "${MAINTENANCE_METRIC_FILE}.$$" "${MAINTENANCE_METRIC_FILE}"
|
||||
}
|
||||
|
||||
echo "=== Maintenance checks ($MODE) $(date -Iseconds) ==="
|
||||
case "$MODE" in
|
||||
daily)
|
||||
check_explorer_sync
|
||||
check_explorer_indexer_lag
|
||||
check_rpc
|
||||
;;
|
||||
weekly)
|
||||
check_config_api
|
||||
check_thin_pool_r630_02
|
||||
echo "[138] Review explorer logs: pct exec 5000 -- journalctl -u blockscout -n 200 --no-pager (from root@${PROXMOX_R630_02})"
|
||||
;;
|
||||
all)
|
||||
check_explorer_sync
|
||||
check_explorer_indexer_lag
|
||||
check_rpc
|
||||
check_config_api
|
||||
check_thin_pool_r630_02
|
||||
echo "[138] Review explorer logs manually; [139] update token list as needed (token-list.json / explorer config)."
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 [daily|weekly|all]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
write_metric_file
|
||||
echo "=== Done (failed: $FAILED) ==="
|
||||
[[ $FAILED -eq 0 ]]
|
||||
30
scripts/maintenance/schedule-daily-weekly-cron.sh
Normal file
30
scripts/maintenance/schedule-daily-weekly-cron.sh
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
# Schedule daily/weekly maintenance checks (O-1, O-2, O-3). Run from project root.
|
||||
# Usage: bash scripts/maintenance/schedule-daily-weekly-cron.sh [--install|--show]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
CHECKS_SCRIPT="$PROJECT_ROOT/scripts/maintenance/daily-weekly-checks.sh"
|
||||
LOG_DIR="$PROJECT_ROOT/logs"
|
||||
CRON_DAILY="0 8 * * * cd $PROJECT_ROOT && bash $CHECKS_SCRIPT daily >> $LOG_DIR/daily-weekly-checks.log 2>&1"
|
||||
CRON_WEEKLY="0 9 * * 0 cd $PROJECT_ROOT && bash $CHECKS_SCRIPT weekly >> $LOG_DIR/daily-weekly-checks.log 2>&1"
|
||||
|
||||
case "${1:-}" in
|
||||
--install)
|
||||
mkdir -p "$LOG_DIR"
|
||||
(crontab -l 2>/dev/null; echo "$CRON_DAILY"; echo "$CRON_WEEKLY") | crontab -
|
||||
echo "Installed daily (08:00) and weekly (Sun 09:00):"
|
||||
echo " $CRON_DAILY"
|
||||
echo " $CRON_WEEKLY"
|
||||
;;
|
||||
--show)
|
||||
echo "Daily (O-1, O-2): $CRON_DAILY"
|
||||
echo "Weekly (O-3): $CRON_WEEKLY"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 [--install|--show]"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
47
scripts/maintenance/schedule-explorer-lag-cron.sh
Normal file
47
scripts/maintenance/schedule-explorer-lag-cron.sh
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
# Schedule cron to check explorer indexer lag and run fix when lag > threshold.
|
||||
# Run from project root. Use a host that can reach RPC and Blockscout (and SSH to r630-02 for fix).
|
||||
# Usage: bash scripts/maintenance/schedule-explorer-lag-cron.sh [--install|--show|--remove]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
LAG_SCRIPT="$PROJECT_ROOT/scripts/maintenance/check-and-fix-explorer-lag.sh"
|
||||
LOG_DIR="$PROJECT_ROOT/logs"
|
||||
LOG_FILE="$LOG_DIR/explorer-lag-fix.log"
|
||||
|
||||
# Every 6 hours (0:00, 6:00, 12:00, 18:00)
|
||||
CRON_LAG="0 */6 * * * cd $PROJECT_ROOT && bash $LAG_SCRIPT >> $LOG_FILE 2>&1"
|
||||
|
||||
case "${1:-}" in
|
||||
--install)
|
||||
mkdir -p "$LOG_DIR"
|
||||
if crontab -l 2>/dev/null | grep -q "check-and-fix-explorer-lag.sh"; then
|
||||
echo "Explorer lag cron already present in crontab."
|
||||
else
|
||||
(crontab -l 2>/dev/null; echo "$CRON_LAG") | crontab -
|
||||
echo "Installed explorer lag cron (every 6 hours):"
|
||||
echo " $CRON_LAG"
|
||||
echo "Log: $LOG_FILE"
|
||||
fi
|
||||
;;
|
||||
--show)
|
||||
echo "Explorer lag check-and-fix (every 6 hours):"
|
||||
echo " $CRON_LAG"
|
||||
echo "Log: $LOG_FILE"
|
||||
echo "Threshold: set EXPLORER_INDEXER_LAG_THRESHOLD (default 500) in crontab or env."
|
||||
;;
|
||||
--remove)
|
||||
if crontab -l 2>/dev/null | grep -q "check-and-fix-explorer-lag.sh"; then
|
||||
crontab -l 2>/dev/null | grep -v "check-and-fix-explorer-lag.sh" | crontab -
|
||||
echo "Removed explorer lag cron."
|
||||
else
|
||||
echo "No explorer lag cron found in crontab."
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 [--install|--show|--remove]"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
25
scripts/maintenance/schedule-npmplus-backup-cron.sh
Normal file
25
scripts/maintenance/schedule-npmplus-backup-cron.sh
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
# Schedule NPMplus backup via cron (W1-8). Run from project root.
|
||||
# Usage: bash scripts/maintenance/schedule-npmplus-backup-cron.sh [--install|--show]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
BACKUP_SCRIPT="$PROJECT_ROOT/scripts/verify/backup-npmplus.sh"
|
||||
CRON_LINE="0 3 * * * cd $PROJECT_ROOT && bash $BACKUP_SCRIPT >> $PROJECT_ROOT/logs/npmplus-backup.log 2>&1"
|
||||
|
||||
case "${1:-}" in
|
||||
--install)
|
||||
mkdir -p "$PROJECT_ROOT/logs"
|
||||
(crontab -l 2>/dev/null; echo "$CRON_LINE") | crontab -
|
||||
echo "Installed: $CRON_LINE"
|
||||
;;
|
||||
--show)
|
||||
echo "Crontab line: $CRON_LINE"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 [--install|--show]"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
37
scripts/maintenance/start-firefly-6201.sh
Executable file
37
scripts/maintenance/start-firefly-6201.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
# Start container 6201 (firefly-ali-1) on r630-02. Optional; run when Firefly Ali node is needed.
|
||||
# Usage: bash scripts/maintenance/start-firefly-6201.sh [--dry-run] [--host HOST]
|
||||
# Requires: SSH key access to the Proxmox host (r630-02).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true
|
||||
[ -f "${PROJECT_ROOT}/.env" ] && set +u && source "${PROJECT_ROOT}/.env" 2>/dev/null; set -u
|
||||
|
||||
VMID=6201
|
||||
PROXMOX_HOST="${PROXMOX_HOST_R630_02:-192.168.11.12}"
|
||||
DRY_RUN=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--dry-run) DRY_RUN=true; shift ;;
|
||||
--host) PROXMOX_HOST="${2:-192.168.11.12}"; shift 2 ;;
|
||||
*) shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
echo "[DRY-RUN] Would run: ssh root@${PROXMOX_HOST} 'pct start ${VMID}'"
|
||||
echo " (Container 6201 = firefly-ali-1 on r630-02. See OPERATIONAL_RUNBOOKS Maintenance.)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Starting CT ${VMID} (firefly-ali-1) on ${PROXMOX_HOST}..."
|
||||
if ssh -o ConnectTimeout=10 -o BatchMode=yes "root@${PROXMOX_HOST}" "pct start ${VMID}"; then
|
||||
echo "Started ${VMID}."
|
||||
else
|
||||
echo "Failed to start ${VMID} (may already be running or host unreachable). Check: ssh root@${PROXMOX_HOST} 'pct status ${VMID}'"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user