hackspace:ausstattung:tv:tvheadend:tvheadend
Inhaltsverzeichnis
TV-Headend
Dokumentation
TvHeadend kann tvkarten verarbeiten und streamen.
Es nutzt tunebare v4l devices.
Docker Run (einfach testen)
docker run -d \ --name tvheadend2 \ --restart unless-stopped \ -e PUID=1000 \ -e PGID=1000 \ -e TZ=Europe/Berlin \ -e RUN_OPTS="" \ -p 9981:9981 \ -p 9982:9982 \ -v /yacht/AppData/tvheadend2/data:/config \ -v /yacht/AppData/tvheadend2/recordings:/recordings \ --device /dev/dri:/dev/dri \ --device /dev/dvb:/dev/dvb \ lscr.io/linuxserver/tvheadend:latest
Dauereinsatz (Grundlage)
#!/usr/bin/env bash
#
# tvheadend2-manage.sh
#
# Management-Script für den TVHeadend-Docker-Container "tvheadend2":
# - install : Erstinstallation / Neuinstallation
# - update : Image aktualisieren + Container neu erstellen
# - clean : Container stoppen + löschen (Daten bleiben erhalten)
# - remove : Alias für "clean"
# - purge : Container + Image + (optional) Daten löschen
# - logs : Logs anzeigen (follow)
# - status : Status anzeigen
# - shell : Shell im Container öffnen
#
# Unterstützt variable Basis-Verzeichnisse:
# - /yacht/AppData/tvheadend2
# - /srv/docker/tvheadend2
#
set -euo pipefail
########################################
# Konfiguration
########################################
# Name des Containers
CONTAINER_NAME="tvheadend2"
# Docker-Image
IMAGE_NAME="lscr.io/linuxserver/tvheadend:latest"
# Standard-Ports (Host:Container)
HTTP_PORT="9981"
HTSP_PORT="9982"
# Mögliche Basisverzeichnisse (Host)
BASE_DIR_CANDIDATES=(
"/yacht/AppData/tvheadend2"
"/srv/docker/tvheadend2"
)
# Effektives Basisverzeichnis bestimmen
BASE_DIR=""
for c in "${BASE_DIR_CANDIDATES[@]}"; do
if [ -d "$c" ]; then
BASE_DIR="$c"
break
fi
done
# Falls noch keins existiert: erstes als Default nehmen und anlegen
if [ -z "$BASE_DIR" ]; then
BASE_DIR="${BASE_DIR_CANDIDATES[0]}"
mkdir -p "$BASE_DIR"
fi
CONFIG_DIR="$BASE_DIR/data"
RECORDINGS_DIR="$BASE_DIR/recordings"
# Default-UID/GID (bei Bedarf anpassen)
PUID="${PUID:-1000}"
PGID="${PGID:-1000}"
########################################
# Hilfsfunktionen
########################################
log() {
echo "[tvh2-manage] $*"
}
ensure_dirs() {
log "Erzeuge Verzeichnisse (falls nicht vorhanden):"
log " CONFIG_DIR = $CONFIG_DIR"
log " RECORDINGS_DIR= $RECORDINGS_DIR"
mkdir -p "$CONFIG_DIR" "$RECORDINGS_DIR"
# Rechte setzen (damit der Container schreiben kann)
log "Setze Eigentümer auf PUID=$PUID, PGID=$PGID"
chown -R "$PUID:$PGID" "$BASE_DIR"
}
container_exists() {
docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"
}
container_running() {
docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"
}
########################################
# Aktionen
########################################
do_install() {
log "Starte INSTALL für $CONTAINER_NAME mit Image $IMAGE_NAME"
ensure_dirs()
if container_exists; then
log "Container $CONTAINER_NAME existiert bereits – entferne alte Instanz..."
docker stop "$CONTAINER_NAME" >/dev/null 2>&1 || true
docker rm "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
log "Pull neues Image..."
docker pull "$IMAGE_NAME"
log "Starte neuen Container mit --restart unless-stopped"
docker run -d \
--name "$CONTAINER_NAME" \
--restart unless-stopped \
-e PUID="$PUID" \
-e PGID="$PGID" \
-e TZ="Europe/Berlin" \
-e RUN_OPTS="" \
-p "${HTTP_PORT}:9981" \
-p "${HTSP_PORT}:9982" \
-v "${CONFIG_DIR}:/config" \
-v "${RECORDINGS_DIR}:/recordings" \
--device /dev/dri:/dev/dri \
--device /dev/dvb:/dev/dvb \
"$IMAGE_NAME"
log "Install/Neu-Deploy abgeschlossen. Web-GUI sollte unter http://<host>:${HTTP_PORT}/ erreichbar sein."
}
do_update() {
log "Starte UPDATE für $CONTAINER_NAME"
ensure_dirs
if ! container_exists; then
log "Container existiert nicht. Führe stattdessen INSTALL aus."
do_install
return
fi
log "Pull neues Image..."
docker pull "$IMAGE_NAME"
log "Stoppe alten Container..."
docker stop "$CONTAINER_NAME" || true
log "Entferne alten Container..."
docker rm "$CONTAINER_NAME" || true
log "Starte Container mit neuem Image..."
docker run -d \
--name "$CONTAINER_NAME" \
--restart unless-stopped \
-e PUID="$PUID" \
-e PGID="$PGID" \
-e TZ="Europe/Berlin" \
-e RUN_OPTS="" \
-p "${HTTP_PORT}:9981" \
-p "${HTSP_PORT}:9982" \
-v "${CONFIG_DIR}:/config" \
-v "${RECORDINGS_DIR}:/recordings" \
--device /dev/dri:/dev/dri \
--device /dev/dvb:/dev/dvb \
"$IMAGE_NAME"
log "Update abgeschlossen."
}
do_clean() {
log "CLEAN: Container stoppen und löschen (Daten bleiben erhalten)."
if container_running; then
log "Stoppe laufenden Container..."
docker stop "$CONTAINER_NAME" || true
fi
if container_exists; then
log "Entferne Container..."
docker rm "$CONTAINER_NAME" || true
else
log "Container existiert nicht – nichts zu tun."
fi
}
do_purge() {
log "PURGE: Container, Image und optional Daten löschen."
# 1) Container stoppen/entfernen
do_clean
# 2) Image löschen
if docker images --format '{{.Repository}}:{{.Tag}}' | grep -q "^${IMAGE_NAME}$"; then
log "Entferne Image $IMAGE_NAME..."
docker rmi "$IMAGE_NAME" || true
else
log "Image $IMAGE_NAME nicht gefunden – überspringe."
fi
# 3) Daten löschen (nur nach expliziter Bestätigung)
echo
echo "WARNUNG: Sollen auch die Datenverzeichnisse gelöscht werden?"
echo " CONFIG_DIR = $CONFIG_DIR"
echo " RECORDINGS_DIR= $RECORDINGS_DIR"
read -r -p "WIRKLICH ALLES LÖSCHEN? (yes/NO): " ans
if [ "$ans" = "yes" ]; then
log "Lösche Datenverzeichnisse..."
rm -rf "$CONFIG_DIR" "$RECORDINGS_DIR"
log "Daten entfernt."
else
log "Daten bleiben erhalten."
fi
}
do_logs() {
log "Zeige Logs von $CONTAINER_NAME (Ctrl+C zum Beenden)..."
docker logs -f "$CONTAINER_NAME"
}
do_status() {
log "Status von $CONTAINER_NAME:"
if container_running; then
echo " - Container läuft."
elif container_exists; then
echo " - Container existiert, läuft aber nicht."
echo " - Letzter Exit-Code siehe: docker inspect $CONTAINER_NAME"
else
echo " - Container existiert nicht."
fi
echo
echo "Gemappte Verzeichnisse:"
echo " BASE_DIR = $BASE_DIR"
echo " CONFIG_DIR = $CONFIG_DIR (-> /config)"
echo " RECORDINGS_DIR= $RECORDINGS_DIR (-> /recordings)"
echo
echo "Image:"
docker images | grep -E 'REPOSITORY|tvheadend|linuxserver/tvheadend|lscr.io/linuxserver/tvheadend' || true
echo
echo "Container:"
docker ps -a | grep -E 'CONTAINER ID|tvheadend2' || true
}
do_shell() {
if ! container_running; then
log "Container läuft nicht – starte ihn kurz an..."
docker start "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
log "Öffne Shell im Container..."
docker exec -it "$CONTAINER_NAME" bash 2>/dev/null || docker exec -it "$CONTAINER_NAME" sh
}
########################################
# Main
########################################
ACTION="${1:-}"
case "$ACTION" in
install)
do_install
;;
update)
do_update
;;
clean|remove)
do_clean
;;
purge)
do_purge
;;
logs)
do_logs
;;
status)
do_status
;;
shell)
do_shell
;;
*)
echo "Usage: $0 {install|update|clean|remove|purge|logs|status|shell}"
echo
echo " install : Container (neu) erstellen mit restart=unless-stopped"
echo " update : Image pullen + Container neu erstellen"
echo " clean : Container stoppen + löschen (Daten bleiben)"
echo " remove : Alias für clean"
echo " purge : Container+Image und optional Daten löschen"
echo " logs : docker logs -f"
echo " status : Übersicht über Container/Image/Verzeichnisse"
echo " shell : Shell in laufendem Container öffnen"
exit 1
;;
esac
/app/www/public/data/pages/hackspace/ausstattung/tv/tvheadend/tvheadend.txt · Zuletzt geändert: von spock0010
