#!/bin/bash # Logseq Installer - Installiert und aktualisiert Logseq auf Linux-Systemen # Autor: Tim Peters # Repository: https://git.tim-peters.org/Tim/Logseq-Installer # ============================================================================= # KONSTANTEN UND KONFIGURATION # ============================================================================= # Farb-Codes für die Terminal-Ausgabe readonly COLOR_RED=$(tput setaf 1) readonly COLOR_GREEN=$(tput setaf 2) readonly COLOR_YELLOW=$(tput setaf 3) readonly COLOR_RESET=$(tput sgr0) # Standardwerte readonly ALLOW_ROOT_DEFAULT=false # Pfad-Konstanten readonly INSTALL_DIR="${HOME}/.local/bin" readonly DESKTOP_DIR="${HOME}/.local/share/applications" readonly SYMLINK_PATH="${INSTALL_DIR}/Logseq" # URLs readonly LOGO_URL="https://raw.githubusercontent.com/logseq/logseq/master/resources/icons/logseq.png" readonly RELEASE_API_URL="https://github.com/logseq/logseq/releases/latest" readonly DOWNLOAD_BASE_URL="https://github.com/logseq/logseq/releases/download" # Dateinamen-Muster readonly APP_NAME="Logseq" readonly APP_IMAGE_PATTERN="Logseq-linux-x64-*.AppImage" readonly DESKTOP_FILE="${DESKTOP_DIR}/logseq.desktop" readonly ICON_FILE="${DESKTOP_DIR}/logseq.png" # ============================================================================= # GLOBALE VARIABLEN # ============================================================================= ALLOW_ROOT="${ALLOW_ROOT_DEFAULT}" VERSION_LATEST="" VERSION_CURRENT="" FILENAME_LOGSEQ="" # ============================================================================= # FEHLERBEHANDLUNG # ============================================================================= # ERR-Trap: Wird bei jedem unbehandelten Befehlsfehler aktiviert trap 'handle_error' ERR # Wird durch die ERR-Trap bei unbehandelten Fehlern aufgerufen handle_error() { local exit_code=$? err "Ein unerwarteter Fehler ist aufgetreten (Exit-Code: ${exit_code})" cat <<-EOT Bitte hilf mit, dieses Skript zu verbessern, und sende einen Fehlerbericht per E-Mail an logseq@testorakel.de EOT exit "${exit_code}" } # ============================================================================= # AUSGABE-HELPER # ============================================================================= # Gibt eine Fehlermeldung in Rot aus und beendet das Skript mit Code 1 err() { echo "${COLOR_RED}$*${COLOR_RESET}" >&2 exit 1 } # Gibt eine Warnung in Gelb auf stderr aus (ohne Abbruch) warn() { echo "${COLOR_YELLOW}$*${COLOR_RESET}" >&2 } # Gibt eine Erfolgsmeldung in Grün aus success() { echo "${COLOR_GREEN}$*${COLOR_RESET}" } # Gibt eine Info-Meldung aus (ohne Farbcode) info() { echo "$*" } # ============================================================================= # ALLGEMEINE HILFSFUNKTIONEN # ============================================================================= # Zeigt das ASCII-Logo an show_logo() { echo -n "${COLOR_GREEN}" cat <<-'EOT' .____ | | ____ ____ ______ ____ ______ | | / _ \ / ___\/ ___// __ \/ ____/ | |__( <_> ) /_/ >___ \\ ___< <_| | |_______ \____/\___ /____ >\___ >__ | \/ /_____/ \/ \/ |__| EOT echo -n "${COLOR_YELLOW}" cat <<-'EOT' .___ __ .__ .__ | | ____ _______/ |______ | | | | ___________ | |/ \ / ___/\ __\__ \ | | | | _/ __ \_ __ \ | | | \\___ \ | | / __ \| |_| |_\ ___/| | \/ |___|___| /____ > |__| (____ /____/____/\___ >__| \/ \/ \/ \/ EOT echo -n "${COLOR_RESET}" } # Zeigt die Hilfe an; optional wird vorher eine Fehlermeldung ausgegeben show_help() { if [[ $# -gt 0 ]]; then echo "$*" echo "" fi cat <<-EOT ${APP_NAME} Installer ================ Erlaubte Optionen: -h | --hilfe --- Zeigt diese Hilfe an -e | --entfernen --- Deinstalliert Logseq -r | --root --- Erlaubt die Installation als root Geschrieben von Tim Peters ---> https://git.tim-peters.org/Tim/Logseq-Installer EOT exit 1 } # Stellt sicher, dass ein benötigter Befehl verfügbar ist require_command() { local cmd="$1" command -v "${cmd}" >/dev/null 2>&1 || err "Befehl '${cmd}' nicht gefunden. Bitte installieren Sie ${cmd}." } # ============================================================================= # VERSIONSERMITTLUNG # ============================================================================= # Ermittelt die neueste verfügbare Version von GitHub get_latest_version() { info "Ermittle neueste verfügbare Version..." # Release-Seite abrufen und Versionsnummer aus dem Redirect-Link extrahieren VERSION_LATEST=$( wget -qO- "${RELEASE_API_URL}" | grep -Po 'releases/tag/\K\d+\.\d+\.\d+' | head -n1 ) [[ -n "${VERSION_LATEST}" ]] || err "Konnte die neueste Version nicht ermitteln." success "Neueste Version: ${VERSION_LATEST}" } # Ermittelt die aktuell installierte Version anhand des neuesten AppImage get_current_version() { info "Ermittle installierte Version..." local latest_appimage # Neueste AppImage-Datei nach Änderungszeitpunkt (mtime) bestimmen latest_appimage=$( find "${INSTALL_DIR}" -maxdepth 1 -name "${APP_IMAGE_PATTERN}" -type f -printf '%T@ %p\n' 2>/dev/null | sort -n | tail -n1 | cut -d' ' -f2- ) if [[ -n "${latest_appimage}" ]]; then VERSION_CURRENT=$(basename "${latest_appimage}" | grep -Po 'Logseq-linux-x64-\K\d+\.\d+\.\d+' | head -n1) if [[ -n "${VERSION_CURRENT}" ]]; then success "Installierte Version: ${VERSION_CURRENT}" else warn "Installierte Version konnte nicht bestimmt werden." fi else VERSION_CURRENT="" info "Logseq ist nicht installiert." fi } # ============================================================================= # INSTALLATION & AKTUALISIERUNG # ============================================================================= # Lädt die neueste Version herunter und installiert sie download_and_install() { local download_url="${DOWNLOAD_BASE_URL}/${VERSION_LATEST}/Logseq-linux-x64-${VERSION_LATEST}.AppImage" local tmp_file info "Lade Logseq ${VERSION_LATEST} herunter..." mkdir -p "${INSTALL_DIR}" # Temp-Datei im Installationsverzeichnis anlegen, damit mv kein Dateisystem-Wechsel benötigt tmp_file=$(mktemp -p "${INSTALL_DIR}") wget --show-progress -qO "${tmp_file}" "${download_url}" || err "Download fehlgeschlagen." FILENAME_LOGSEQ=$(basename "${download_url}") mv -f "${tmp_file}" "${INSTALL_DIR}/${FILENAME_LOGSEQ}" || err "Verschieben der Datei fehlgeschlagen." chmod u+x "${INSTALL_DIR}/${FILENAME_LOGSEQ}" || err "Berechtigungen setzen fehlgeschlagen." # Alte Versionen entfernen und Symlink auf die neue Version aktualisieren cleanup_old_versions ln -sf "${INSTALL_DIR}/${FILENAME_LOGSEQ}" "${SYMLINK_PATH}" || err "Symlink erstellen fehlgeschlagen." success "Logseq ${VERSION_LATEST} erfolgreich installiert." } # Entfernt alte AppImage-Versionen bis auf die aktuell installierte cleanup_old_versions() { local current_file="${INSTALL_DIR}/${FILENAME_LOGSEQ}" # Alle AppImages außer der aktuellen Datei löschen find "${INSTALL_DIR}" -maxdepth 1 -name "${APP_IMAGE_PATTERN}" -type f ! -path "${current_file}" -delete 2>/dev/null || true } # Erstellt den Desktop-Eintrag für das Startmenü create_desktop_entry() { info "Erstelle Desktop-Eintrag..." # Icon herunterladen falls nicht vorhanden if [[ ! -f "${ICON_FILE}" ]]; then info "Lade Icon herunter..." wget -qO "${ICON_FILE}" "${LOGO_URL}" || warn "Icon konnte nicht heruntergeladen werden." fi cat > "${DESKTOP_FILE}" <<-EOF [Desktop Entry] Encoding=UTF-8 Name=Logseq Comment=Wissensmanagement mit Logseq Exec=${INSTALL_DIR}/${FILENAME_LOGSEQ} --no-sandbox Icon=${ICON_FILE} Type=Application Categories=Office; X-GNOME-SingleWindow=true SingleMainWindow=true EOF update-desktop-database "${DESKTOP_DIR}" 2>/dev/null || true success "Desktop-Eintrag erstellt." } # Deinstalliert Logseq vollständig uninstall_logseq() { info "Deinstalliere Logseq..." # AppImage(s) und Symlink entfernen rm -f "${SYMLINK_PATH}" rm -f "${INSTALL_DIR}"/Logseq-linux-x64-*.AppImage # Desktop-Eintrag und Icon entfernen rm -f "${DESKTOP_FILE}" "${ICON_FILE}" update-desktop-database "${DESKTOP_DIR}" 2>/dev/null || true success "Logseq wurde vollständig deinstalliert." exit 0 } # Prüft, ob Logseq gerade läuft (Update nur bei beendeter Instanz) check_running() { # pgrep-Flags: -i (case-insensitive), -f (volle Kommandozeile), # -c (Anzahl Treffer), -x (exakte Übereinstimmung der Kommandozeile) if pgrep -ifcx "${SYMLINK_PATH}" >/dev/null; then err "Logseq läuft noch. Bitte beenden Sie Logseq vor dem Update." fi } # ============================================================================= # KOMMANDOZEILEN-ARGUMENTE & ROOT-PRÜFUNG # ============================================================================= # Parst Kommandozeilenargumente (kurz und lang) parse_arguments() { local optspec=":her-:" local OPT OPTARG while getopts "${optspec}" OPT; do [[ "${OPT}" == " " ]] && continue # Lange Option (--wort oder --wort=wert) auflösen if [[ "${OPT}" == "-" ]]; then OPT="${OPTARG%%=*}" OPTARG="${OPTARG#"${OPT}"}" OPTARG="${OPTARG#=}" fi case "${OPT}" in h | hilfe) show_help ;; e | entfernen) uninstall_logseq ;; r | root) ALLOW_ROOT=true ;; \?) show_help "Unbekannte Option: -${OPTARG}" ;; *) show_help "Unbekannte Option: --${OPT}" ;; esac done shift $((OPTIND - 1)) } # Verhindert die Ausführung als root, außer wenn explizit erlaubt check_root_permissions() { if [[ "$(whoami)" == "root" && "${ALLOW_ROOT}" == "false" ]]; then show_help "Die Installation sollte nicht als root erfolgen (Option -r/--root erlaubt es)." fi } # ============================================================================= # MAIN # ============================================================================= main() { # Abhängigkeiten prüfen require_command "wget" require_command "pgrep" require_command "find" # Kommandozeilenargumente parsen parse_arguments "$@" # Root-Prüfung check_root_permissions # Logo anzeigen show_logo # Versionen ermitteln get_latest_version get_current_version # Versionsvergleich info "Neueste verfügbare Version...... ${COLOR_GREEN}${VERSION_LATEST}${COLOR_RESET}" info "Derzeit installierte Version... ${COLOR_GREEN}${VERSION_CURRENT:-${COLOR_RED}Logseq ist nicht installiert${COLOR_RESET}}" # Bereits aktuell? if [[ "${VERSION_CURRENT}" == "${VERSION_LATEST}" ]]; then success "Logseq ist bereits auf dem neuesten Stand." exit 0 fi # Prüfen ob Logseq läuft check_running # Installation durchführen download_and_install create_desktop_entry success "Logseq wurde erfolgreich installiert/aktualisiert." } # ============================================================================= # EINSTIEGSPUNKT # ============================================================================= main "$@"