Initial Phoenix analyzer
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||
PHOENIX_ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
|
||||
PHOENIX_PARENT="$(cd "$PHOENIX_ROOT/.." && pwd -P)"
|
||||
PHOENIX_NAME="$(basename "$PHOENIX_ROOT")"
|
||||
STAGE_DIR="$PHOENIX_PARENT/${PHOENIX_NAME}.update"
|
||||
BACKUP_DIR="$PHOENIX_PARENT/${PHOENIX_NAME}.backup"
|
||||
FAILED_DIR="$PHOENIX_PARENT/${PHOENIX_NAME}.failed"
|
||||
LOG_FILE="$PHOENIX_PARENT/${PHOENIX_NAME}.update.log"
|
||||
|
||||
exec >>"$LOG_FILE" 2>&1
|
||||
echo "=== $(date): restart_phoenix_services.sh START ==="
|
||||
|
||||
restart_if_present() {
|
||||
local unit="$1"
|
||||
if ! command -v systemctl >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
if run_systemctl list-unit-files "$unit" >/dev/null 2>&1 || run_systemctl status "$unit" >/dev/null 2>&1; then
|
||||
run_systemctl restart "$unit" >/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
stop_if_present() {
|
||||
local unit="$1"
|
||||
if ! command -v systemctl >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
if run_systemctl list-unit-files "$unit" >/dev/null 2>&1 || run_systemctl status "$unit" >/dev/null 2>&1; then
|
||||
run_systemctl stop "$unit" >/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
run_systemctl() {
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
systemctl "$@"
|
||||
return $?
|
||||
fi
|
||||
if ! command -v sudo >/dev/null 2>&1; then
|
||||
echo "sudo not found; cannot control system services as non-root" >&2
|
||||
return 1
|
||||
fi
|
||||
sudo -n systemctl "$@"
|
||||
}
|
||||
|
||||
run_systemd_run() {
|
||||
local unit_name="phoenix-online-update-$(date +%s)"
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
systemd-run --unit="$unit_name" --collect --property=Type=oneshot \
|
||||
/usr/bin/env PHOENIX_UPDATE_DETACHED=1 /bin/bash "$0"
|
||||
return $?
|
||||
fi
|
||||
if ! command -v sudo >/dev/null 2>&1; then
|
||||
echo "sudo not found; cannot detach update restart as non-root" >&2
|
||||
return 1
|
||||
fi
|
||||
sudo -n systemd-run --unit="$unit_name" --collect --property=Type=oneshot \
|
||||
/usr/bin/env PHOENIX_UPDATE_DETACHED=1 /bin/bash "$0"
|
||||
}
|
||||
|
||||
health_ok() {
|
||||
if ! command -v curl >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
curl -fsS http://127.0.0.1:8789/health >/dev/null 2>&1
|
||||
}
|
||||
|
||||
needs_phoenix_build() {
|
||||
local phoenix_dir="${1:-$PHOENIX_ROOT}"
|
||||
local phoenix_bin="$phoenix_dir/target/release/phoenix"
|
||||
if [ ! -x "$phoenix_bin" ] || [ ! -s "$phoenix_bin" ]; then
|
||||
return 0
|
||||
fi
|
||||
if [ -f "$phoenix_dir/Cargo.toml" ] && [ "$phoenix_dir/Cargo.toml" -nt "$phoenix_bin" ]; then
|
||||
return 0
|
||||
fi
|
||||
if [ -f "$phoenix_dir/Cargo.lock" ] && [ "$phoenix_dir/Cargo.lock" -nt "$phoenix_bin" ]; then
|
||||
return 0
|
||||
fi
|
||||
if [ -d "$phoenix_dir/src" ] && find "$phoenix_dir/src" -type f -name '*.rs' -newer "$phoenix_bin" -print -quit | grep -q .; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
clear_browser_asset_caches() {
|
||||
local cache_roots=(
|
||||
"/data/chrome-analyzer/Default/Cache"
|
||||
"/data/chrome-analyzer/Default/Code Cache"
|
||||
"/data/chrome-analyzer/Default/GPUCache"
|
||||
"/data/chrome-dualtabs/Default/Cache"
|
||||
"/data/chrome-dualtabs/Default/Code Cache"
|
||||
"/data/chrome-dualtabs/Default/GPUCache"
|
||||
)
|
||||
local path
|
||||
for path in "${cache_roots[@]}"; do
|
||||
if [ -e "$path" ]; then
|
||||
rm -rf "$path" || true
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
wait_for_health() {
|
||||
local attempts="${1:-30}"
|
||||
local delay="${2:-1}"
|
||||
local i
|
||||
for i in $(seq 1 "$attempts"); do
|
||||
if health_ok; then
|
||||
return 0
|
||||
fi
|
||||
sleep "$delay"
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
wait_for_candidate_health() {
|
||||
local phoenix_dir="${1:-$PHOENIX_ROOT}"
|
||||
local attempts="${2:-45}"
|
||||
local delay="${3:-1}"
|
||||
local start_try
|
||||
local max_start_tries="${PHOENIX_UPDATE_START_TRIES:-3}"
|
||||
|
||||
if needs_phoenix_build "$phoenix_dir"; then
|
||||
attempts="${PHOENIX_UPDATE_BUILD_HEALTH_ATTEMPTS:-420}"
|
||||
echo "Phoenix tree requires local rebuild; extending health wait to ${attempts}s"
|
||||
else
|
||||
echo "Phoenix tree already has runnable binary; health wait ${attempts}s"
|
||||
fi
|
||||
|
||||
for start_try in $(seq 1 "$max_start_tries"); do
|
||||
echo "starting Phoenix services health attempt ${start_try}/${max_start_tries}"
|
||||
start_all_services
|
||||
if wait_for_health "$attempts" "$delay"; then
|
||||
echo "Phoenix health OK on attempt ${start_try}/${max_start_tries}"
|
||||
return 0
|
||||
fi
|
||||
echo "Phoenix health failed on attempt ${start_try}/${max_start_tries}"
|
||||
stop_all_services
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
start_all_services() {
|
||||
restart_if_present phoenix.service
|
||||
restart_if_present analyzer-web.service
|
||||
restart_if_present analyzer-web-volumio.service
|
||||
clear_browser_asset_caches
|
||||
restart_if_present analyzer-kiosk.service
|
||||
restart_if_present analyzer-kiosk-volumio.service
|
||||
}
|
||||
|
||||
stop_all_services() {
|
||||
stop_if_present analyzer-kiosk.service
|
||||
stop_if_present analyzer-kiosk-volumio.service
|
||||
stop_if_present analyzer-web.service
|
||||
stop_if_present analyzer-web-volumio.service
|
||||
stop_if_present phoenix.service
|
||||
}
|
||||
|
||||
rollback_to_backup() {
|
||||
stop_all_services
|
||||
rm -rf "$FAILED_DIR"
|
||||
if [ -d "$PHOENIX_ROOT" ]; then
|
||||
mv "$PHOENIX_ROOT" "$FAILED_DIR"
|
||||
fi
|
||||
if [ ! -d "$BACKUP_DIR" ]; then
|
||||
echo "backup missing; cannot roll back to $BACKUP_DIR" >&2
|
||||
return 1
|
||||
fi
|
||||
mv "$BACKUP_DIR" "$PHOENIX_ROOT"
|
||||
if ! wait_for_candidate_health "$PHOENIX_ROOT" "${PHOENIX_ROLLBACK_HEALTH_ATTEMPTS:-120}" 1; then
|
||||
echo "backup rollback restored files but Phoenix health did not recover" >&2
|
||||
return 1
|
||||
fi
|
||||
echo "rollback to backup succeeded"
|
||||
}
|
||||
|
||||
if [ "${PHOENIX_UPDATE_DETACHED:-0}" != "1" ]; then
|
||||
if ! command -v systemd-run >/dev/null 2>&1; then
|
||||
echo "systemd-run not found; cannot safely detach updater" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "detaching updater into transient systemd unit"
|
||||
if run_systemd_run; then
|
||||
echo "detached updater started"
|
||||
exit 0
|
||||
fi
|
||||
echo "failed to start detached updater" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$STAGE_DIR" ]; then
|
||||
echo "staged update missing: $STAGE_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "$STAGE_DIR/Cargo.toml" ] || [ ! -d "$STAGE_DIR/src" ] || [ ! -d "$STAGE_DIR/www" ] || [ ! -d "$STAGE_DIR/scripts" ]; then
|
||||
echo "staged update invalid: $STAGE_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
stop_all_services
|
||||
|
||||
rm -rf "$BACKUP_DIR"
|
||||
if [ -d "$PHOENIX_ROOT" ]; then
|
||||
mv "$PHOENIX_ROOT" "$BACKUP_DIR"
|
||||
fi
|
||||
mv "$STAGE_DIR" "$PHOENIX_ROOT"
|
||||
|
||||
health_attempts=45
|
||||
health_delay=1
|
||||
|
||||
if ! wait_for_candidate_health "$PHOENIX_ROOT" "$health_attempts" "$health_delay"; then
|
||||
if ! rollback_to_backup; then
|
||||
echo "new Phoenix version failed health check and rollback failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "new Phoenix version failed health check; rolled back to backup" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== $(date): restart_phoenix_services.sh OK ==="
|
||||
@@ -0,0 +1,102 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ZIP_URL="${1:-https://webshare.casaderoll.de/share/Phoenix.zip}"
|
||||
PHOENIX_ROOT="${2:-}"
|
||||
|
||||
if [ -z "$PHOENIX_ROOT" ] || [ ! -d "$PHOENIX_ROOT" ]; then
|
||||
echo "invalid Phoenix root: $PHOENIX_ROOT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TMP_BASE="${TMPDIR:-/tmp}"
|
||||
WORK_DIR="$(mktemp -d "$TMP_BASE/phoenix-update.XXXXXX")"
|
||||
ZIP_PATH="$WORK_DIR/phoenix.zip"
|
||||
EXTRACT_DIR="$WORK_DIR/extract"
|
||||
PHOENIX_PARENT="$(cd "$PHOENIX_ROOT/.." && pwd -P)"
|
||||
PHOENIX_NAME="$(basename "$PHOENIX_ROOT")"
|
||||
STAGE_DIR="$PHOENIX_PARENT/${PHOENIX_NAME}.update"
|
||||
LOG_FILE="$PHOENIX_PARENT/${PHOENIX_NAME}.update.log"
|
||||
|
||||
exec >>"$LOG_FILE" 2>&1
|
||||
echo "=== $(date): update_phoenix_from_zip.sh START ==="
|
||||
echo "ZIP_URL=$ZIP_URL"
|
||||
echo "PHOENIX_ROOT=$PHOENIX_ROOT"
|
||||
echo "STAGE_DIR=$STAGE_DIR"
|
||||
|
||||
cleanup() {
|
||||
echo "cleanup work dir: $WORK_DIR"
|
||||
rm -rf "$WORK_DIR"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
mkdir -p "$EXTRACT_DIR"
|
||||
|
||||
if ! command -v curl >/dev/null 2>&1; then
|
||||
echo "curl not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
extract_zip() {
|
||||
local zip_path="$1"
|
||||
local extract_dir="$2"
|
||||
|
||||
if command -v unzip >/dev/null 2>&1; then
|
||||
unzip -oq "$zip_path" -d "$extract_dir"
|
||||
return
|
||||
fi
|
||||
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
python3 -m zipfile -e "$zip_path" "$extract_dir"
|
||||
return
|
||||
fi
|
||||
|
||||
echo "no zip extractor found: install unzip or python3" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "downloading update archive..."
|
||||
curl -fL "$ZIP_URL" -o "$ZIP_PATH"
|
||||
echo "download complete: $ZIP_PATH"
|
||||
extract_zip "$ZIP_PATH" "$EXTRACT_DIR"
|
||||
echo "archive extracted to: $EXTRACT_DIR"
|
||||
|
||||
SOURCE_DIR=""
|
||||
while IFS= read -r candidate; do
|
||||
if [ -f "$candidate/Cargo.toml" ] && [ -d "$candidate/www" ] && [ -d "$candidate/src" ]; then
|
||||
SOURCE_DIR="$candidate"
|
||||
break
|
||||
fi
|
||||
done < <(find "$EXTRACT_DIR" -mindepth 0 -maxdepth 4 -type d | sort)
|
||||
|
||||
if [ -z "$SOURCE_DIR" ]; then
|
||||
echo "no Phoenix project found inside update archive" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "source project root: $SOURCE_DIR"
|
||||
|
||||
# Build-Artefakte und Mac-Reste nie mitdeployen.
|
||||
find "$SOURCE_DIR" -type d \( -name target -o -name .git \) -prune -exec rm -rf {} +
|
||||
find "$SOURCE_DIR" -type f \( -name '.DS_Store' -o -name 'Thumbs.db' \) -delete
|
||||
echo "source tree cleaned"
|
||||
|
||||
rm -rf "$STAGE_DIR"
|
||||
mkdir -p "$STAGE_DIR"
|
||||
echo "stage dir prepared"
|
||||
|
||||
if command -v rsync >/dev/null 2>&1; then
|
||||
rsync -a --delete --omit-dir-times --no-perms --no-owner --no-group \
|
||||
"$SOURCE_DIR"/ "$STAGE_DIR"/
|
||||
else
|
||||
echo "rsync not found; using cp fallback"
|
||||
cp -a "$SOURCE_DIR"/. "$STAGE_DIR"/
|
||||
fi
|
||||
echo "stage sync complete"
|
||||
|
||||
if [ ! -f "$STAGE_DIR/Cargo.toml" ] || [ ! -d "$STAGE_DIR/src" ] || [ ! -d "$STAGE_DIR/www" ] || [ ! -d "$STAGE_DIR/scripts" ]; then
|
||||
echo "staged update is incomplete: $STAGE_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "staged update validated"
|
||||
echo "=== $(date): update_phoenix_from_zip.sh OK ==="
|
||||
Reference in New Issue
Block a user