#!/bin/sh # # Bootstrap instalace HAVIS III WebServer ze zrcadla get.havis.cz # # Použití (na stanici s přístupem k mirroru): # wget -qO- https://get.havis.cz | sh # poslední verze # wget -qO- https://get.havis.cz | sh -s -- 3.7.2026042001 # konkrétní verze # # Skript je čisté POSIX sh (žádné bashismy) - na stanicích běží # různé shelly. Celé tělo je ve funkcích a main se volá až na úplně # posledním řádku, takže useknuté stažení nikdy nespustí půlku skriptu. # # Heslo se čte z /dev/tty (stdin je obsazený rourou z wget) a předává # se wgetu přes dočasný netrc soubor - nikdy není v URL, argumentech # ani ve výpisu procesů. MIRROR_HOST="get.havis.cz" BASE_URL="https://${MIRROR_HOST}/dist" AUTH_USER="havis" MAX_AUTH_ATTEMPTS=3 TMP_DIR="" STTY_SAVED="" PASSWORD="" msg() { printf '%s\n' "$*" } err() { printf 'CHYBA: %s\n' "$*" >&2 } cleanup() { # Obnov echo na terminálu (kdyby skript skončil uprostřed zadávání hesla) if [ -n "$STTY_SAVED" ] && [ -e /dev/tty ]; then stty "$STTY_SAVED" < /dev/tty 2>/dev/null || true fi # Smaž dočasný adresář včetně netrc a stažených souborů if [ -n "$TMP_DIR" ] && [ -d "$TMP_DIR" ]; then rm -rf "$TMP_DIR" fi } require_cmd() { if ! command -v "$1" > /dev/null 2>&1; then err "Na této stanici chybí nástroj '$1'. Bez něj instalace nemůže pokračovat." exit 1 fi } ask_password() { printf 'Zadej heslo pro stažení (uživatel %s): ' "$AUTH_USER" > /dev/tty STTY_SAVED=$(stty -g < /dev/tty) stty -echo < /dev/tty IFS= read -r PASSWORD < /dev/tty stty "$STTY_SAVED" < /dev/tty STTY_SAVED="" printf '\n' > /dev/tty } write_netrc() { # Dočasný netrc s právy 600 - vytvořit prázdný a zamknout DŘÍV, # než se do něj zapíše heslo : > "$TMP_DIR/.netrc" chmod 600 "$TMP_DIR/.netrc" printf 'machine %s\nlogin %s\npassword %s\n' \ "$MIRROR_HOST" "$AUTH_USER" "$PASSWORD" > "$TMP_DIR/.netrc" } # fetch [progress] # wget čte přihlašovací údaje z $HOME/.netrc, proto mu podstrčíme # dočasný HOME - heslo se nedostane do argumentů příkazu. fetch() { if [ "${3:-}" = "progress" ]; then HOME="$TMP_DIR" wget -q --show-progress -O "$2" "$1" else HOME="$TMP_DIR" wget -q -O "$2" "$1" fi } main() { VERSION="${1:-}" echo "" msg "=========================================" msg " Instalace HAVIS III WebServer" msg "=========================================" echo "" require_cmd wget require_cmd sha256sum require_cmd mktemp require_cmd stty if [ ! -e /dev/tty ] || [ ! -r /dev/tty ]; then err "Není dostupný terminál pro zadání hesla." err "Spusť skript v normálním terminálu (SSH nebo konzole stanice)." exit 1 fi TMP_DIR=$(mktemp -d) || { err "Nepodařilo se vytvořit dočasný adresář."; exit 1; } trap cleanup EXIT trap 'exit 130' INT trap 'exit 143' TERM if [ -n "$VERSION" ]; then RUN_NAME="havisIII_WebServer-${VERSION}.run" msg "Požadovaná verze: $VERSION" else RUN_NAME="latest.run" msg "Bude nainstalována poslední dostupná verze." fi echo "" # --- Přihlášení + stažení checksumu (malý soubor = rychlé ověření hesla) --- attempt=1 while :; do ask_password write_netrc msg "Ověřuji přihlášení a dostupnost balíčku..." rc=0 fetch "$BASE_URL/$RUN_NAME.sha256" "$TMP_DIR/$RUN_NAME.sha256" || rc=$? if [ "$rc" -eq 0 ]; then break fi if [ "$rc" -eq 6 ]; then # wget exit kód 6 = chyba přihlášení (HTTP 401) if [ "$attempt" -ge "$MAX_AUTH_ATTEMPTS" ]; then echo "" err "Třikrát zadané špatné heslo - instalace ukončena." err "Ověř si heslo a spusť instalaci znovu. Pokud heslo neznáš, ozvi se správci." exit 1 fi attempt=$((attempt + 1)) msg "Špatné heslo, zkus to prosím znovu (pokus $attempt z $MAX_AUTH_ATTEMPTS)." echo "" elif [ "$rc" -eq 8 ]; then # HTTP chyba jiná než 401 - typicky 404 echo "" if [ -n "$VERSION" ]; then err "Balíček pro verzi '$VERSION' na serveru není." err "Zkontroluj číslo verze, nebo spusť instalaci bez verze (nainstaluje se poslední)." else err "Na serveru zatím není žádný balíček k instalaci. Ozvi se správci." fi exit 1 else echo "" err "Nepodařilo se připojit k $MIRROR_HOST (wget exit kód $rc)." err "Zkontroluj, že je stanice připojená k síti s přístupem na mirror." exit 1 fi done msg "Přihlášení v pořádku." echo "" # Skutečný název balíčku je uvnitř checksumu (latest.run je symlink) REAL_NAME=$(awk '{print $2; exit}' "$TMP_DIR/$RUN_NAME.sha256" | sed 's/^\*//') if [ -n "$REAL_NAME" ]; then msg "Instalovaný balíček: $REAL_NAME" fi # --- Stažení balíčku --- msg "Stahuji balíček (může to chvíli trvat)..." if ! fetch "$BASE_URL/$RUN_NAME" "$TMP_DIR/$RUN_NAME" progress; then echo "" err "Stažení balíčku selhalo. Zkus instalaci spustit znovu." exit 1 fi msg "Balíček stažen." echo "" # --- Ověření kontrolního součtu --- msg "Ověřuji kontrolní součet..." EXPECTED=$(awk '{print $1; exit}' "$TMP_DIR/$RUN_NAME.sha256") ACTUAL=$(sha256sum "$TMP_DIR/$RUN_NAME" | awk '{print $1}') if [ -z "$EXPECTED" ] || [ "$EXPECTED" != "$ACTUAL" ]; then err "Kontrolní součet staženého balíčku nesouhlasí!" err "Soubor je poškozený nebo neúplný - spusť instalaci znovu." err "Pokud problém přetrvává, ozvi se správci." exit 1 fi msg "Kontrolní součet v pořádku." echo "" # --- Spuštění instalace --- msg "Spouštím instalaci (další kroky si řekne instalátor sám)..." echo "" # stdin přesměrovat na terminál - roura z wget už je vyčerpaná # a instalátor se ptá na potvrzení a sudo heslo sh "$TMP_DIR/$RUN_NAME" < /dev/tty echo "" msg "=========================================" msg " Instalace dokončena" msg "=========================================" } main "$@"