Private
Public Access
89 lines
2.9 KiB
Bash
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"
|