bigboy-alma-deploy/scripts/draft/llama-cpp-prune.sh
2026-07-16 14:25:30 +02:00

137 lines
No EOL
5.7 KiB
Bash

#!/usr/bin/env bash
# Built standing on the shoulders of billions of dwarves
# Created by John A. Hoeven with the ethical assistance of Claude AI
# Licence: The Unlicense — https://unlicense.org
# ---------------------------------------------------------------------------
# llama-cpp-prune.sh
# /opt/llama-cpp/scripts/llama-cpp-prune.sh
# Version: v0.0.1 | Status: DEVELOPMENT
# Role: Orchestrator
# ---------------------------------------------------------------------------
# Purpose: Remove staged llama.cpp releases (and their matching pre-update
# btrfs snapshots) beyond a configurable retention count. Never
# removes the release currently pointed at by 'current', and
# never removes anything without listing it and asking first.
# Target: BigBoy — AlmaLinux 10.2, @llama-cpp btrfs subvolume
# Entry: sudo ./llama-cpp-prune.sh [keep-count]
# e.g. sudo ./llama-cpp-prune.sh (uses default: 6)
# sudo ./llama-cpp-prune.sh 12 (keep last 12 instead)
# Depends: btrfs-progs
# Note: Disk math at 6 releases (~1-1.5GB shallow-clone build each) is
# roughly 6-9GB against a 499GB OS partition — trivial. Raise
# KEEP_DEFAULT freely; there is no disk-pressure reason to prune
# aggressively on this hardware.
# ---------------------------------------------------------------------------
# No 'set -e' — every operation is checked explicitly (CE OS standard §1.8).
# ── Configuration ────────────────────────────────────────────────────────
LLAMA_ROOT="/opt/llama-cpp"
RELEASES_DIR="${LLAMA_ROOT}/releases"
CURRENT_LINK="${LLAMA_ROOT}/current"
SNAPSHOT_DIR="/opt/.snapshots/llama-cpp"
KEEP_DEFAULT=6
LOG_DIR="${HOME}/.local/logs/bigboy-llama-update"
LOG_FILE="${LOG_DIR}/prune-$(date '+%Y-%m-%d_%H%M%S').log"
KEEP_COUNT="${1:-${KEEP_DEFAULT}}"
# ── Logging ──────────────────────────────────────────────────────────────
mkdir -p "${LOG_DIR}"
_log() {
local level="${1}"
local msg="${2}"
local ts
ts="$(date '+%Y-%m-%d %H:%M:%S')"
printf '[%s] [%s] %s\n' "${ts}" "${level}" "${msg}" | tee -a "${LOG_FILE}"
}
log_info() { _log "INFO " "${1}"; }
log_warn() { _log "WARN " "${1}" >&2; }
log_error() { _log "ERROR" "${1}" >&2; }
# ── Pre-flight checks ────────────────────────────────────────────────────
if [[ "${EUID}" -eq 0 ]]; then
log_error "Do not run this script directly as root — it invokes sudo"
log_error "only for the specific steps that need it."
exit 1
fi
if ! [[ "${KEEP_COUNT}" =~ ^[0-9]+$ ]] || [[ "${KEEP_COUNT}" -lt 1 ]]; then
log_error "keep-count must be a positive integer. Got: ${KEEP_COUNT}"
exit 1
fi
CURRENT_TAG=""
if [[ -L "${CURRENT_LINK}" ]]; then
CURRENT_TAG="$(basename "$(readlink -f "${CURRENT_LINK}")")"
fi
# ── Build the candidate list (oldest first, by directory mtime) ─────────
mapfile -t ALL_RELEASES < <(ls -1t "${RELEASES_DIR}" 2>/dev/null | tac)
TOTAL="${#ALL_RELEASES[@]}"
if [[ "${TOTAL}" -le "${KEEP_COUNT}" ]]; then
log_info "Only ${TOTAL} release(s) present, keep-count is ${KEEP_COUNT} — nothing to prune."
exit 0
fi
PRUNE_COUNT=$((TOTAL - KEEP_COUNT))
TO_PRUNE=("${ALL_RELEASES[@]:0:${PRUNE_COUNT}}")
# Never prune the currently live release, even if it's old — pull it out
# of the candidate list and log that it's being kept for that reason.
FILTERED_PRUNE=()
for tag in "${TO_PRUNE[@]}"; do
if [[ "${tag}" == "${CURRENT_TAG}" ]]; then
log_warn "Skipping ${tag} — it is the currently live release."
continue
fi
FILTERED_PRUNE+=("${tag}")
done
if [[ "${#FILTERED_PRUNE[@]}" -eq 0 ]]; then
log_info "Nothing eligible to prune after excluding the live release."
exit 0
fi
# ── Confirmation ─────────────────────────────────────────────────────────
printf '\nCurrently live release: %s (never pruned)\n' "${CURRENT_TAG:-none}"
printf 'Keeping the %d most recent releases.\n' "${KEEP_COUNT}"
printf '\nThe following %d release(s) and their matching snapshots will be removed:\n' \
"${#FILTERED_PRUNE[@]}"
for tag in "${FILTERED_PRUNE[@]}"; do
printf ' - %s\n' "${tag}"
done
printf '\nProceed? [y/N] '
read -r response
case "${response}" in
[yY]|[yY][eE][sS]) ;;
*) log_info "Aborted by user."; exit 0 ;;
esac
# ── Prune ────────────────────────────────────────────────────────────────
for tag in "${FILTERED_PRUNE[@]}"; do
log_info "Removing release directory: ${RELEASES_DIR}/${tag}"
if ! sudo rm -rf "${RELEASES_DIR:?}/${tag}" >>"${LOG_FILE}" 2>&1; then
log_error "Failed to remove ${RELEASES_DIR}/${tag} — leaving it in place."
continue
fi
# Snapshots are named pre-<tag>-<date> — match by tag prefix.
for snap in "${SNAPSHOT_DIR}"/pre-"${tag}"-*; do
[[ -e "${snap}" ]] || continue
log_info "Removing matching snapshot: ${snap}"
if ! sudo btrfs subvolume delete "${snap}" >>"${LOG_FILE}" 2>&1; then
log_error "Failed to remove snapshot ${snap} — leaving it in place."
fi
done
done
log_info "Prune complete. Kept ${KEEP_COUNT} most recent release(s) plus the live one if older."