Files
Halloween/tools/install_pi_service.sh
T

89 lines
2.9 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
project_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd -P)
service_name=halloween-grab.service
unit_path="/etc/systemd/system/$service_name"
apply=false
usage() {
cat <<'EOF'
Richtet die Halloween-WebUI als systemd-Dienst auf dem Raspberry Pi ein.
Aufruf: bash tools/install_pi_service.sh [--apply]
Ohne --apply wird nur die geplante Unit gezeigt. --apply installiert sie mit
sudo, aktiviert den Autostart und startet die WebUI sofort neu.
EOF
}
die() {
printf 'Fehler: %s\n' "$*" >&2
exit 2
}
while (($#)); do
case $1 in
--apply) apply=true; shift ;;
-h|--help) usage; exit 0 ;;
*) die "Unbekanntes Argument: $1" ;;
esac
done
service_user=$(id -un)
[[ $service_user =~ ^[a-zA-Z_][a-zA-Z0-9_-]*$ ]] || die 'Ungeeigneter Benutzername für systemd'
[[ $service_user != root ]] || die 'Skript als normaler Pi-Benutzer ausführen, nicht als root'
[[ $project_dir =~ ^/[a-zA-Z0-9_./-]+$ ]] || die 'Projektpfad enthält für die Unit ungeeignete Zeichen'
[[ /$project_dir/ != *'/../'* && /$project_dir/ != *'/./'* ]] || die 'Projektpfad enthält . oder .. Segmente'
unit_contents=$(cat <<EOF
# Managed by Halloween project: tools/install_pi_service.sh
[Unit]
Description=Halloween-Grab WebUI und Kamera
After=network.target
[Service]
Type=simple
User=$service_user
WorkingDirectory=$project_dir
ExecStart=$project_dir/.venv/bin/python $project_dir/run.py
Environment=PYTHONUNBUFFERED=1
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
EOF
)
printf 'Dienst: %s\nBenutzer: %s\nProjekt: %s\n' "$service_name" "$service_user" "$project_dir"
if ! $apply; then
printf '\nVorschau für %s:\n%s\n' "$unit_path" "$unit_contents"
printf '\nMit --apply installieren, aktivieren und starten.\n'
exit 0
fi
[[ -f "$project_dir/run.py" ]] || die 'run.py fehlt im Projektordner'
[[ -x "$project_dir/.venv/bin/python" ]] || die '.venv fehlt; zuerst SOFTWARE.md: Pi vorbereiten ausführen'
"$project_dir/.venv/bin/python" -c 'import fastapi, uvicorn, PIL' \
|| die 'Python-Abhängigkeiten fehlen; zuerst requirements.txt installieren'
command -v sudo >/dev/null || die 'sudo fehlt'
command -v systemctl >/dev/null || die 'systemctl fehlt'
if sudo test -e "$unit_path" &&
! sudo grep -qF '# Managed by Halloween project: tools/install_pi_service.sh' "$unit_path"; then
die "Vorhandene fremde Unit wird nicht überschrieben: $unit_path"
fi
temp_unit=$(mktemp)
trap 'rm -f -- "$temp_unit"' EXIT
printf '%s\n' "$unit_contents" > "$temp_unit"
sudo install -m 0644 -- "$temp_unit" "$unit_path"
sudo systemctl daemon-reload
sudo systemctl enable "$service_name"
sudo systemctl restart "$service_name"
if ! systemctl is-active --quiet "$service_name"; then
die "Dienst läuft nicht; Diagnose: sudo journalctl -u $service_name -n 80 --no-pager"
fi
printf 'Autostart aktiviert und Dienst gestartet. Status: systemctl status %s\n' "$service_name"