Files
qortal-DevNet-scripts/create-devnet-db-archive.sh

176 lines
5.1 KiB
Bash
Executable File

#!/usr/bin/env bash
set -eEuo pipefail
IFS=$'\n\t'
### Configuration ###
REMOTE_USER="crowetic"
REMOTE_HOST="devnet-nodes.qortal.link"
REMOTE_PORT=22225
REMOTE_BASE_DIR="/qortal" # stop.sh, start.sh, db/, qortal.jar live here
LOCAL_SYNC_DIR="/mnt/4TB-WDB/DATA/QortalCloud/DevNet"
MAX_LOCAL_AGE_DAYS=2 # roll new remote archive only if local copy ≥ this
KEEP_LOCAL_ARCHIVES=2 # keep this many archives locally
#######################
log(){ echo "[$(date +'%H:%M:%S')] $*"; }
trap 'log "ERROR: script failed at line $LINENO"; exit 1' ERR
# Function to retry rsync with exponential backoff
rsync_with_retry() {
local max_attempts=3
local attempt=1
local success=0
while (( attempt <= max_attempts )); do
if "$@"; then
success=1
break
else
log "rsync attempt $attempt failed. Retrying in $((attempt * 5)) seconds..."
sleep $((attempt * 5))
((attempt++))
fi
done
if (( success == 0 )); then
log "ERROR: rsync failed after $max_attempts attempts"
exit 1
fi
}
# 1) Inspect the newest local archive
log "Inspecting local archives…"
LATEST_LOCAL=$(ls -1t "${LOCAL_SYNC_DIR}"/db-Devnet-*.7z 2>/dev/null | head -1 || true)
if [[ -n "$LATEST_LOCAL" ]]; then
TS=$(stat -c %Y "$LATEST_LOCAL")
AGE=$(( ( $(date +%s) - TS ) / 86400 ))
log "→ Found ${LATEST_LOCAL##*/}, age=${AGE}d"
else
log "→ No local archives found."
AGE=$((MAX_LOCAL_AGE_DAYS+1))
fi
# 2) Conditionally roll a new archive on remote
if (( AGE >= MAX_LOCAL_AGE_DAYS )); then
NEW_ARCH="db-Devnet-$(date +%Y%m%d_%H%M%S).7z"
log "→ Local ≥${MAX_LOCAL_AGE_DAYS}d old; creating ${NEW_ARCH} on remote"
ssh -p"${REMOTE_PORT}" "${REMOTE_USER}@${REMOTE_HOST}" bash -l <<EOF
set -euxo pipefail
cd "${REMOTE_BASE_DIR}"
command -v 7z >/dev/null || { echo "ERROR: install p7zip-full"; exit 1; }
# stop.sh (ignore failure)
if [[ -x ./stop.sh ]]; then
set +e; ./stop.sh; set -e
fi
[[ -d db ]] || { echo "ERROR: db/ missing"; exit 1; }
7z a "${NEW_ARCH}" db
# restart (best effort)
if [[ -x ./start.sh ]]; then
./start.sh
fi
# prune remote: keep only the newest 1 archive
ls -1t db-Devnet-*.7z \
| tail -n +2 \
| xargs -r rm -f --
EOF
# fetch the newly created archive
log "Rsyncing new archive → local"
rsync_with_retry rsync -avPz -e "ssh -p${REMOTE_PORT}" \
"${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_BASE_DIR}/${NEW_ARCH}" \
"${LOCAL_SYNC_DIR}/"
else
log "→ Local archive is fresh (<${MAX_LOCAL_AGE_DAYS}d); skipping archive creation."
fi
# 3) Always rsync qortal.jar
log "Rsyncing qortal.jar → local (primary)"
rsync_with_retry rsync -avPz -e "ssh -p${REMOTE_PORT}" \
"${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_BASE_DIR}/qortal.jar" \
"${LOCAL_SYNC_DIR}/"
log "Rsyncing qortal.jar → local devnet folder"
PRIMARY_JAR="${LOCAL_SYNC_DIR}/qortal.jar"
DEVNET_JAR="${LOCAL_SYNC_DIR}/qortal-DevNet/qortal.jar"
if [[ -f "$PRIMARY_JAR" ]]; then
rsync_with_retry rsync -a "$PRIMARY_JAR" "$DEVNET_JAR"
else
log "ERROR: no local qortal.jar found after rsync"
exit 1
fi
log "Rsyncing settings.json → local (primary)"
rsync_with_retry rsync -avPz -e "ssh -p${REMOTE_PORT}" \
"${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_BASE_DIR}/settings.json" \
"${LOCAL_SYNC_DIR}/"
log "Rsyncing settings.json → local devnet folder"
rsync_with_retry rsync -a \
"${LOCAL_SYNC_DIR}/settings.json" \
"${LOCAL_SYNC_DIR}/qortal-DevNet/settings.json"
log "Updating hash.txt from the newest local qortal.jar"
PRIMARY_JAR="${LOCAL_SYNC_DIR}/qortal.jar"
DEVNET_JAR="${LOCAL_SYNC_DIR}/qortal-DevNet/qortal.jar"
HASH_INPUT=""
if [[ -f "$PRIMARY_JAR" && -f "$DEVNET_JAR" ]]; then
if [[ "$PRIMARY_JAR" -nt "$DEVNET_JAR" ]]; then
HASH_INPUT="$PRIMARY_JAR"
else
HASH_INPUT="$DEVNET_JAR"
fi
elif [[ -f "$PRIMARY_JAR" ]]; then
HASH_INPUT="$PRIMARY_JAR"
elif [[ -f "$DEVNET_JAR" ]]; then
HASH_INPUT="$DEVNET_JAR"
else
log "ERROR: no local qortal.jar found to hash"
exit 1
fi
md5sum "$HASH_INPUT" | awk '{print $1}' > "${LOCAL_SYNC_DIR}/hash.txt"
log "hash.txt updated from ${HASH_INPUT}"
SRC_DIR="${LOCAL_SYNC_DIR}/qortal-DevNet"
ARCHIVE="${LOCAL_SYNC_DIR}/qortal-DevNet-MAIN.7z"
TMP_DIR="${LOCAL_SYNC_DIR}/temp"
TMP_ARCHIVE="${LOCAL_SYNC_DIR}/temp.7z"
log() { echo "[$(date +'%F %T')] $*"; }
# 1. If there is no archive, or if any file in SRC_DIR is newer than ARCHIVE, rebuild.
if [[ ! -f "$ARCHIVE" ]] || find "$SRC_DIR" -type f -newer "$ARCHIVE" | read; then
log "Changes detected (or no archive yet). Rebuilding 7z…"
# Clean temp
rm -rf "$TMP_DIR"
mkdir -p "$TMP_DIR"
# Mirror the tree in temp
rsync_with_retry rsync -a --delete "$SRC_DIR/" "$TMP_DIR/"
# Create the archive
7z a "$TMP_ARCHIVE" "$TMP_DIR"
# Atomically replace the old archive
mv -f "$TMP_ARCHIVE" "$ARCHIVE"
log "Archive updated at $ARCHIVE"
else
log "No changes since last archive; skipping rebuild."
fi
# 4) Prune local archives: keep only the newest $KEEP_LOCAL_ARCHIVES
log "Pruning local archives to the ${KEEP_LOCAL_ARCHIVES} most recent"
cd "${LOCAL_SYNC_DIR}"
ls -1t db-Devnet-*.7z \
| tail -n +$((KEEP_LOCAL_ARCHIVES+1)) \
| xargs -r rm -f --
log "✔ Done."