154 lines
4.4 KiB
Bash
Executable File
154 lines
4.4 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
PROJECT_ROOT=$(dirname "$SCRIPT_DIR")
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage: update/debug.sh [--keep] [arch|ubuntu] [-- update-args...]
|
|
|
|
Spins up a temporary VM-like container, mounts the repository, and runs the update
|
|
script with UPDATE_DEBUG=1. Requires podman (preferred) or docker with systemd
|
|
support. Pass --keep to leave the container running for inspection. Any arguments
|
|
after -- are forwarded to update/update.sh.
|
|
USAGE
|
|
}
|
|
|
|
KEEP_CONTAINER=0
|
|
DISTRO=""
|
|
FORWARDED_ARGS=()
|
|
|
|
while (( $# )); do
|
|
case "$1" in
|
|
--keep)
|
|
KEEP_CONTAINER=1
|
|
shift
|
|
;;
|
|
arch|ubuntu)
|
|
DISTRO="$1"
|
|
shift
|
|
;;
|
|
--)
|
|
shift
|
|
FORWARDED_ARGS=("$@")
|
|
break
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$DISTRO" ]]; then
|
|
DISTRO="ubuntu"
|
|
fi
|
|
|
|
case "$DISTRO" in
|
|
arch)
|
|
IMAGE="docker.io/archlinux:latest"
|
|
INIT_PATH="/usr/lib/systemd/systemd"
|
|
PREPARE_CMD='pacman -Syyu --noconfirm sudo git base-devel';
|
|
;;
|
|
ubuntu)
|
|
IMAGE="docker.io/library/ubuntu:24.04"
|
|
INIT_PATH="/sbin/init"
|
|
PREPARE_CMD='apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y sudo git'
|
|
;;
|
|
*)
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
if command -v podman >/dev/null 2>&1; then
|
|
RUNTIME="podman"
|
|
MOUNT_OPTS=":Z"
|
|
elif command -v docker >/dev/null 2>&1; then
|
|
RUNTIME="docker"
|
|
MOUNT_OPTS=""
|
|
else
|
|
echo "[!] Neither podman nor docker found in PATH." >&2
|
|
exit 1
|
|
fi
|
|
|
|
CONTAINER_NAME="linuxbox-update-debug-${DISTRO}-$$"
|
|
|
|
cleanup() {
|
|
if (( KEEP_CONTAINER )); then
|
|
echo "[i] Keeping container ${CONTAINER_NAME} running for inspection." >&2
|
|
return
|
|
fi
|
|
if "$RUNTIME" ps -a --format '{{.Names}}' 2>/dev/null | grep -qx "$CONTAINER_NAME"; then
|
|
"$RUNTIME" rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
start_container() {
|
|
if [[ "$RUNTIME" == "podman" ]]; then
|
|
"$RUNTIME" run -d --name "$CONTAINER_NAME" --privileged \
|
|
--tmpfs /tmp --tmpfs /run \
|
|
-v /sys/fs/cgroup:/sys/fs/cgroup:ro \
|
|
-v "$PROJECT_ROOT:/workspace${MOUNT_OPTS}" \
|
|
-w /workspace "$IMAGE" "$INIT_PATH" >/dev/null
|
|
else
|
|
"$RUNTIME" run -d --name "$CONTAINER_NAME" --privileged --cgroupns=host \
|
|
--tmpfs /tmp --tmpfs /run \
|
|
-v /sys/fs/cgroup:/sys/fs/cgroup:ro \
|
|
-v "$PROJECT_ROOT:/workspace" \
|
|
-w /workspace "$IMAGE" "$INIT_PATH" >/dev/null
|
|
fi
|
|
}
|
|
|
|
wait_for_systemd() {
|
|
local attempts=0
|
|
while (( attempts < 30 )); do
|
|
local status
|
|
status=$("$RUNTIME" exec "$CONTAINER_NAME" systemctl is-system-running 2>/dev/null || true)
|
|
case "$status" in
|
|
running|degraded)
|
|
return 0
|
|
;;
|
|
esac
|
|
sleep 1
|
|
((attempts++))
|
|
done
|
|
echo "[!] systemd did not reach running state inside container (last status: $status)." >&2
|
|
}
|
|
|
|
bootstrap_container() {
|
|
if [[ "$DISTRO" == "ubuntu" ]]; then
|
|
"$RUNTIME" exec "$CONTAINER_NAME" bash -lc "export DEBIAN_FRONTEND=noninteractive; $PREPARE_CMD"
|
|
"$RUNTIME" exec "$CONTAINER_NAME" bash -lc "useradd -m debugger || true"
|
|
"$RUNTIME" exec "$CONTAINER_NAME" bash -lc "echo 'debugger ALL=(ALL) NOPASSWD:ALL' >/etc/sudoers.d/debugger && chmod 0440 /etc/sudoers.d/debugger"
|
|
else
|
|
"$RUNTIME" exec "$CONTAINER_NAME" bash -lc "$PREPARE_CMD"
|
|
"$RUNTIME" exec "$CONTAINER_NAME" bash -lc "useradd -m debugger || true"
|
|
"$RUNTIME" exec "$CONTAINER_NAME" bash -lc "echo 'debugger ALL=(ALL) NOPASSWD:ALL' >/etc/sudoers.d/debugger && chmod 0440 /etc/sudoers.d/debugger"
|
|
fi
|
|
"$RUNTIME" exec "$CONTAINER_NAME" bash -lc "chown -R debugger:debugger /workspace"
|
|
}
|
|
|
|
run_update() {
|
|
local update_cmd
|
|
printf -v update_cmd 'UPDATE_DEBUG=1 ./update/update.sh %q' "$DISTRO"
|
|
for arg in "${FORWARDED_ARGS[@]}"; do
|
|
printf -v update_cmd '%s %q' "$update_cmd" "$arg"
|
|
done
|
|
"$RUNTIME" exec "$CONTAINER_NAME" bash -lc "su - debugger -c \"cd /workspace && $update_cmd\""
|
|
}
|
|
|
|
start_container
|
|
wait_for_systemd
|
|
bootstrap_container
|
|
run_update
|
|
|
|
echo "[✓] Debug run completed." >&2
|