From 352c3520563e68540e3ab38593796b5dd9a7d54e Mon Sep 17 00:00:00 2001 From: Mathias Scheider Date: Fri, 27 Mar 2026 12:41:00 +0100 Subject: [PATCH] init at home --- Computerkram/Docker.md | 780 +++++++++++ .../JavaScript/JavaScript Tutorial.md | 740 ++++++++++ .../Notiz (anbei) überarbeiten.md | 6 + Computerkram/LibrechatAI.md | 1 + .../Linux/AppImage Programme einrichten.md | 164 +++ Computerkram/Linux/BASH Basics/BASH Basics.md | 40 + .../Linux/BASH Basics/BASH Funktionen.md | 693 +++++++++ .../Linux/BASH Basics/Dateiberechtigungen.md | 365 +++++ .../Linux/BASH Basics/PATH und Alias.md | 115 ++ Computerkram/Linux/BASH Basics/Symlinks.md | 107 ++ Computerkram/Linux/BASH Basics/awk.md | 257 ++++ Computerkram/Linux/BASH Basics/find.md | 362 +++++ .../Linux/BASH Basics/fstab Credentials.md | 127 ++ Computerkram/Linux/BASH Basics/grep.md | 202 +++ Computerkram/Linux/BASH Basics/ls.md | 390 ++++++ Computerkram/Linux/BASH Basics/lsblk.md | 177 +++ Computerkram/Linux/BASH Basics/rsync.md | 275 ++++ Computerkram/Linux/BASH Basics/sed.md | 270 ++++ Computerkram/Linux/BASH Basics/tar.md | 354 +++++ ...Skript mit Argumenten und Weiterleitung.md | 243 ++++ .../Zugriff auf den Skript-Pfad in BASH.md | 132 ++ Computerkram/Linux/Boot Menü anpassen.md | 407 ++++++ ...ootfähigen USB-Stick mit `dd` erstellen.md | 85 ++ .../Linux/Disable KVM for VirtualBox.md | 76 + .../Linux/Displaylink Installation.md | 418 ++++++ Computerkram/Linux/Hyprland/Stow mit Logik.md | 140 ++ Computerkram/Linux/Linux .desktop Dateien.md | 23 + Computerkram/Linux/Linux Drum Plugins.md | 29 + .../Linux/Linux Konsole Zeichen löschen.md | 32 + Computerkram/Linux/Linux Musikprogramme.md | 272 ++++ Computerkram/Linux/Linux Terminal Shortcut.md | 34 + Computerkram/Linux/Linux.md | 15 + Computerkram/Linux/Meine Config.md | 3 + .../Linux/Navidrome mit Strawberry.md | 142 ++ Computerkram/Linux/Navidrome.md | 97 ++ ...ketinstallation in Linux-Distributionen.md | 99 ++ Computerkram/Linux/SSH Verbindung in Linux.md | 101 ++ Computerkram/Linux/SSH-Schlüssel erzeugen.md | 162 +++ Computerkram/Linux/Strawberry.md | 137 ++ Computerkram/Linux/Subsonic-API.md | 119 ++ .../Linux/Synchronisation & Backup.md | 472 +++++++ Computerkram/Linux/Timeshift.md | 230 +++ ...-Stick unter Linux per Bash formatieren.md | 111 ++ Computerkram/Linux/VIM Cheat Sheet.md | 458 ++++++ Computerkram/Linux/Wine.md | 232 +++ Computerkram/Linux/mein fstab.md | 106 ++ Computerkram/Linux/snapper.md | 479 +++++++ Computerkram/Navidrome Rescan.md | 84 ++ Computerkram/Open WebUI.md | 207 +++ Computerkram/Python/argpase.md | 385 +++++ ... Web Project From Scratch (Real Python).md | 342 +++++ ...mmy Webseite über WWW (Chatbot Session).md | 374 +++++ ...bdesign Start - aller Anfang ist schwer.md | 10 + .../etc/fstab - Bsp buntes_monster.md | 17 + Computerkram/git/Git_Fork_Guide.md | 74 + Computerkram/git/Ignore & Untrack.md | 63 + Computerkram/neovim-setup.md | 1247 +++++++++++++++++ sync-at-home.sh | 1 + 58 files changed, 13083 insertions(+) create mode 100644 Computerkram/Docker.md create mode 100644 Computerkram/JavaScript/JavaScript Tutorial.md create mode 100644 Computerkram/KI Prompt Templates/Notiz (anbei) überarbeiten.md create mode 100644 Computerkram/LibrechatAI.md create mode 100644 Computerkram/Linux/AppImage Programme einrichten.md create mode 100644 Computerkram/Linux/BASH Basics/BASH Basics.md create mode 100644 Computerkram/Linux/BASH Basics/BASH Funktionen.md create mode 100644 Computerkram/Linux/BASH Basics/Dateiberechtigungen.md create mode 100644 Computerkram/Linux/BASH Basics/PATH und Alias.md create mode 100644 Computerkram/Linux/BASH Basics/Symlinks.md create mode 100644 Computerkram/Linux/BASH Basics/awk.md create mode 100644 Computerkram/Linux/BASH Basics/find.md create mode 100644 Computerkram/Linux/BASH Basics/fstab Credentials.md create mode 100644 Computerkram/Linux/BASH Basics/grep.md create mode 100644 Computerkram/Linux/BASH Basics/ls.md create mode 100644 Computerkram/Linux/BASH Basics/lsblk.md create mode 100644 Computerkram/Linux/BASH Basics/rsync.md create mode 100644 Computerkram/Linux/BASH Basics/sed.md create mode 100644 Computerkram/Linux/BASH Basics/tar.md create mode 100644 Computerkram/Linux/BASH Skripte/BASH Skript mit Argumenten und Weiterleitung.md create mode 100644 Computerkram/Linux/BASH Skripte/Zugriff auf den Skript-Pfad in BASH.md create mode 100644 Computerkram/Linux/Boot Menü anpassen.md create mode 100644 Computerkram/Linux/Bootfähigen USB-Stick mit `dd` erstellen.md create mode 100644 Computerkram/Linux/Disable KVM for VirtualBox.md create mode 100644 Computerkram/Linux/Displaylink Installation.md create mode 100644 Computerkram/Linux/Hyprland/Stow mit Logik.md create mode 100644 Computerkram/Linux/Linux .desktop Dateien.md create mode 100644 Computerkram/Linux/Linux Drum Plugins.md create mode 100644 Computerkram/Linux/Linux Konsole Zeichen löschen.md create mode 100644 Computerkram/Linux/Linux Musikprogramme.md create mode 100644 Computerkram/Linux/Linux Terminal Shortcut.md create mode 100644 Computerkram/Linux/Linux.md create mode 100644 Computerkram/Linux/Meine Config.md create mode 100644 Computerkram/Linux/Navidrome mit Strawberry.md create mode 100644 Computerkram/Linux/Navidrome.md create mode 100644 Computerkram/Linux/Paketinstallation in Linux-Distributionen.md create mode 100644 Computerkram/Linux/SSH Verbindung in Linux.md create mode 100644 Computerkram/Linux/SSH-Schlüssel erzeugen.md create mode 100644 Computerkram/Linux/Strawberry.md create mode 100644 Computerkram/Linux/Subsonic-API.md create mode 100644 Computerkram/Linux/Synchronisation & Backup.md create mode 100644 Computerkram/Linux/Timeshift.md create mode 100644 Computerkram/Linux/USB-Stick unter Linux per Bash formatieren.md create mode 100644 Computerkram/Linux/VIM Cheat Sheet.md create mode 100644 Computerkram/Linux/Wine.md create mode 100644 Computerkram/Linux/mein fstab.md create mode 100644 Computerkram/Linux/snapper.md create mode 100644 Computerkram/Navidrome Rescan.md create mode 100644 Computerkram/Open WebUI.md create mode 100644 Computerkram/Python/argpase.md create mode 100644 Computerkram/Webseiten, selbstgehostet/Build a Scalable Flask Web Project From Scratch (Real Python).md create mode 100644 Computerkram/Webseiten, selbstgehostet/Flask Dummy Webseite über WWW (Chatbot Session).md create mode 100644 Computerkram/Webseiten, selbstgehostet/Webdesign Start - aller Anfang ist schwer.md create mode 100644 Computerkram/etc/fstab - Bsp buntes_monster.md create mode 100644 Computerkram/git/Git_Fork_Guide.md create mode 100644 Computerkram/git/Ignore & Untrack.md create mode 100644 Computerkram/neovim-setup.md create mode 100644 sync-at-home.sh diff --git a/Computerkram/Docker.md b/Computerkram/Docker.md new file mode 100644 index 0000000..6966733 --- /dev/null +++ b/Computerkram/Docker.md @@ -0,0 +1,780 @@ + +--- + +# 🐳 Einführung in Docker + +## 1. Was ist Docker? + +Docker ist eine Plattform, mit der du **Container** erstellen, starten und verwalten kannst. +Ein Container ist eine Art "leichtgewichtige virtuelle Maschine": + +- Enthält **nur das Nötigste** (Programm, Abhängigkeiten, Bibliotheken). +- Läuft isoliert, aber nutzt den Kernel des Host-Systems (kein eigener Kernel wie bei einer VM). +- Ist **schneller** und **ressourcenschonender** als klassische VMs. + +👉 Bildlich: Statt für jedes Programm einen eigenen PC (VM) aufzubauen, packst du nur das Programm in eine "Transportbox" (Container), die überall läuft, solange Docker installiert ist. + +--- + +## 2. Vorteile und typische Anwendungsfälle + +### Vorteile + +- **Portabilität**: „Läuft auf meinem Rechner“ = „läuft auch auf Servern“. +- **Isolierung**: Verschiedene Programme/Versionen stören sich nicht. +- **Leichtgewicht**: Start in Sekunden statt Minuten wie bei VMs. +- **Reproduzierbarkeit**: Gleiche Umgebung für Entwicklung, Test und Produktion. +- **Einfache Verteilung**: Images können über Docker Hub oder private Registries geteilt werden. + +### Typische Anwendungsfälle + +- 🚀 **Entwicklung**: Z. B. [[Python]] 3.10 testen, obwohl auf dem System Python 3.12 läuft. +- 🗄️ **Datenbanken**: [[MySQL]], PostgreSQL, Redis, MongoDB zum Testen ohne Installation. +- 🌐 **Web-Apps**: Schnell mal eine fertige Anwendung ausprobieren (WordPress, Nextcloud, GitLab etc.). +- 🧪 **Testing**: Mehrere Umgebungen simulieren (verschiedene OS, Bibliotheksversionen). +- 📦 **Deployment**: Gleiche App auf mehreren Servern identisch bereitstellen. + +--- + +## 3. Hauptfunktionalitäten von Docker + +- **Docker Engine**: Herzstück, das Container ausführt. +- **Docker Images**: Baupläne (Templates) für Container (z. B. Python 3.12 + Flask). +- **Docker Containers**: Laufende Instanzen von Images. +- **Docker Hub/Registry**: Cloud-Marktplatz für fertige Images. +- **Docker Compose**: Orchestrierung mehrerer Container (z. B. App + DB + Cache). + +--- + +## 4. Installation unter Linux (Beispiel: Ubuntu/Debian) + +```bash +# 1. Alte Versionen entfernen +sudo apt-get remove docker docker-engine docker.io containerd runc + +# 2. Repository vorbereiten +sudo apt-get update +sudo apt-get install -y ca-certificates curl gnupg + +# Docker GPG-Key hinzufügen +sudo install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \ + sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg + +# Repository einrichten +echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \ + https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + +# 3. Docker installieren +sudo apt-get update +sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + +# 4. Testen +sudo docker run hello-world +``` + +👉 Danach kannst du optional dich in die `docker`-Gruppe aufnehmen (sonst musst du immer `sudo` schreiben): + +```bash +sudo usermod -aG docker $USER +# Abmelden/neu anmelden, damit es wirkt +``` + +--- + +## 5. Erste Schritte in der Praxis + +### Beispiel 1: Linux — Container starten + +```bash +# Einen Ubuntu-Container starten (interaktiv) +docker run -it ubuntu bash + +# Danach bist du im Container: +root@:/# cat /etc/os-release +``` + +Wenn du rausgehst (`exit`), bleibt der Container gespeichert. + +--- + +### Beispiel 2: Linux — Nginx-Webserver starten + +```bash +# Nginx starten, Port 8080 weiterleiten +docker run -d -p 8080:80 nginx + +# Nun im Browser: http://localhost:8080 +``` + +--- + +### Beispiel 3: Python im Container + +Nehmen wir an, du willst ein Python-Skript in einer isolierten Umgebung ausführen. + +**hello.py** + +```python +print("Hello from Dockerized Python!") +``` + +**Dockerfile** + +```dockerfile +FROM python:3.11-slim + +# Skript ins Image kopieren +COPY hello.py /app/hello.py + +# Arbeitsverzeichnis setzen +WORKDIR /app + +# Default-Befehl +CMD ["python", "hello.py"] +``` + +**Bauen und starten** + +```bash +# Image bauen +docker build -t mypythonapp . + +# Container starten +docker run --rm mypythonapp +``` + +Ausgabe: + +``` +Hello from Dockerized Python! +``` + +--- + +### Beispiel 4: Python mit externer Bibliothek + +```python +# requirements.txt +flask==3.0.0 +``` + +**app.py** + +```python +from flask import Flask +app = Flask(__name__) + +@app.route("/") +def hello(): + return "Hello, Docker!" + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=5000) +``` + +**Dockerfile** + +```dockerfile +FROM python:3.11-slim + +WORKDIR /app + +COPY requirements.txt . +RUN pip install -r requirements.txt + +COPY app.py . + +CMD ["python", "app.py"] +``` + +**Starten** + +```bash +docker build -t flaskapp . +docker run -d -p 5000:5000 flaskapp +``` + +👉 Browser öffnen: `http://localhost:5000` + +--- + +## 6. Nützliche Docker-Befehle (Cheatsheet) + +- `docker ps` – laufende Container +- `docker ps -a` – alle Container (inkl. gestoppter) +- `docker images` – vorhandene Images +- `docker stop ` – Container stoppen +- `docker rm ` – Container löschen +- `docker rmi ` – Image löschen +- `docker exec -it bash` – in Container einsteigen + +--- + +✅ Damit hast du einen vollständigen Überblick über Docker: + +- **Grundidee** +- **Vorteile/Anwendungsfälle** +- **Installation** +- **Praxis mit Linux und Python** + +--- +# Anwendungsbeispiel +# 🐳 Docker Anwendungsbeispiel - Detaillierte Erklärung für Einsteiger + +## 📚 Was ist Docker überhaupt? + +**Docker** ist wie ein **"Umzugskarton für Software"**: +- Stell Dir vor, Du willst Deine App an einen Freund verschicken +- Statt nur den Code zu senden, packst Du **alles** ein: Code, Python, alle Bibliotheken, Konfiguration +- Dein Freund öffnet den "Karton" (Container) und alles läuft sofort - egal welches Betriebssystem er hat + +--- + +## 📁 Projektstruktur mit Erklärungen + +``` +python-docker-project/ +├── app/ # 📂 Unser Python-Code +│ ├── __init__.py # (macht 'app' zu einem Python-Paket) +│ ├── main.py # Hauptprogramm +│ ├── data_processor.py # Modul für Datenverarbeitung +│ └── database.py # Modul für Datenbankzugriff +├── input/ # 📁 Hier liegen die Input-Dateien (vom Host) +│ └── sample_data.csv # Beispieldatei +├── output/ # 📁 Hier kommen verarbeitete Dateien rein +├── requirements.txt # 📝 Liste aller Python-Pakete die wir brauchen +├── Dockerfile # 🐳 "Bauanleitung" für unseren Container +├── docker-compose.yml # 🎼 "Dirigent" für mehrere Container +└── .env # 🔐 Geheime Einstellungen (Passwörter etc.) +``` + +--- + +## 🐍 Python-Code (wie gewohnt) + +### **requirements.txt** - "Einkaufsliste" für Python-Pakete +```txt +# 🛒 Diese Pakete braucht unser Programm +pandas==2.1.4 # Für Excel/CSV-Verarbeitung +psycopg2-binary==2.9.9 # Um mit PostgreSQL zu sprechen +python-dotenv==1.0.0 # Um .env-Dateien zu lesen +sqlalchemy==2.0.23 # Einfache Datenbankanbindung +``` + +**💡 Warum brauche ich das?** +- Ohne Docker müsstest Du auf jedem PC manuell `pip install pandas` etc. machen +- Mit Docker installiert sich das automatisch im Container + +### **app/main.py** - Unser Hauptprogramm +```python +#!/usr/bin/env python3 +""" +🎯 Das macht unser Programm: +1. Schaut in /app/input nach CSV-Dateien +2. Verarbeitet sie (quadriert Werte, etc.) +3. Speichert Ergebnis in PostgreSQL-Datenbank +4. Exportiert auch als CSV in /app/output +""" +import os +import time +from pathlib import Path +from dotenv import load_dotenv + +from .data_processor import DataProcessor +from .database import DatabaseManager + +def main(): + print("🚀 Starte Data Processing Pipeline...") + + # 📁 Diese Pfade sind INSIDE dem Container! + input_dir = Path("/app/input") # Gemountet von Host ./input/ + output_dir = Path("/app/output") # Gemountet von Host ./output/ + output_dir.mkdir(exist_ok=True) + + # 🗄️ Verbindung zur Datenbank (anderer Container!) + db_manager = DatabaseManager() + processor = DataProcessor(db_manager) + + # 📊 Alle CSV-Dateien finden und verarbeiten + csv_files = list(input_dir.glob("*.csv")) + + if not csv_files: + print("❌ Keine CSV-Dateien im Input-Verzeichnis gefunden!") + return + + for csv_file in csv_files: + print(f"📄 Verarbeite: {csv_file.name}") + + # 1️⃣ Daten aus CSV laden und verarbeiten + result_data = processor.process_file(csv_file) + + # 2️⃣ In PostgreSQL-Container speichern + processor.save_to_database(result_data, csv_file.stem) + + # 3️⃣ Als neue CSV-Datei exportieren + output_file = output_dir / f"processed_{csv_file.name}" + result_data.to_csv(output_file, index=False) + print(f"💾 Gespeichert als: {output_file}") + + print("✅ Pipeline abgeschlossen!") + +if __name__ == "__main__": + main() +``` + +### **app/database.py** - Spricht mit der Datenbank +```python +import os +import pandas as pd +from sqlalchemy import create_engine, text + +class DatabaseManager: + def __init__(self): + # 🔌 Diese Werte kommen aus der docker-compose.yml! + self.host = os.getenv('DB_HOST', 'postgres') # Name des DB-Containers! + self.port = os.getenv('DB_PORT', '5432') + self.database = os.getenv('DB_NAME', 'dataprocessing') + self.user = os.getenv('DB_USER', 'postgres') + self.password = os.getenv('DB_PASSWORD', 'password') + + # 🌐 Connection String - wie eine Adresse zur Datenbank + self.connection_string = ( + f"postgresql://{self.user}:{self.password}@" + f"{self.host}:{self.port}/{self.database}" + ) + + self.engine = None + self._connect() + + def _connect(self): + """Verbindung zur Datenbank herstellen""" + try: + self.engine = create_engine(self.connection_string) + # 🏓 Kurzer Test: "Hallo Datenbank!" + with self.engine.connect() as conn: + conn.execute(text("SELECT 1")) + print("✅ Datenbankverbindung erfolgreich") + except Exception as e: + print(f"❌ Datenbankverbindung fehlgeschlagen: {e}") + raise + + def save_dataframe(self, df: pd.DataFrame, table_name: str): + """Speichert DataFrame als Tabelle in PostgreSQL""" + df.to_sql( + name=table_name, + con=self.engine, + if_exists='replace', # Überschreibt existierende Tabelle + index=False + ) +``` + +*(Die anderen Python-Dateien bleiben gleich)* + +--- + +## 🐳 Dockerfile - "Bauanleitung" für unseren Container + +```dockerfile +# 🏗️ SCHRITT 1: Basis-Image wählen +# Das ist wie ein "Rohbau" - Linux + Python sind schon installiert +FROM python:3.11-slim + +# 🛠️ SCHRITT 2: System-Tools installieren +# Wir brauchen gcc und libpq-dev für PostgreSQL-Verbindung +RUN apt-get update && apt-get install -y \ + gcc \ + libpq-dev \ + && rm -rf /var/lib/apt/lists/* + +# 💡 WARUM: psycopg2 (PostgreSQL-Driver) braucht diese Tools zum Kompilieren + +# 📂 SCHRITT 3: Arbeitsverzeichnis setzen +WORKDIR /app +# Das ist wie "cd /app" - alle folgenden Befehle laufen hier + +# 📦 SCHRITT 4: Python-Pakete installieren +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt +# 💡 WARUM separat? Docker cached diesen Layer - muss nur neu gebaut werden wenn requirements.txt ändert + +# 📋 SCHRITT 5: Unseren Code ins Container kopieren +COPY app/ ./app/ +# Kopiert alles aus Host-Ordner "app/" nach Container "/app/app/" + +# 📁 SCHRITT 6: Verzeichnisse erstellen +RUN mkdir -p /app/input /app/output +# Diese werden später durch Volume-Mounts "überschrieben" + +# ⚙️ SCHRITT 7: Umgebungsvariablen setzen +ENV PYTHONPATH=/app # Python findet unsere Module +ENV PYTHONUNBUFFERED=1 # Print-Ausgaben erscheinen sofort + +# 🚀 SCHRITT 8: Was soll beim Container-Start passieren? +CMD ["python", "-m", "app.main"] +# Startet unser Hauptprogramm +``` + +**🤔 Was passiert beim `docker build`?** +1. Docker lädt `python:3.11-slim` herunter (falls nicht da) +2. Installiert gcc und PostgreSQL-Tools +3. Kopiert `requirements.txt` und installiert Python-Pakete +4. Kopiert unseren Code rein +5. Setzt Umgebungsvariablen +6. **Ergebnis:** Ein fertiger Container mit allem was wir brauchen! + +--- + +## 🎼 docker-compose.yml - "Dirigent" für mehrere Container + +```yaml +# 🎯 docker-compose orchestriert MEHRERE Container gleichzeitig +version: '3.8' + +services: + # 🗄️ CONTAINER 1: PostgreSQL-Datenbank + postgres: + image: postgres:15 # Fertiges PostgreSQL-Image von Docker Hub + environment: # Umgebungsvariablen für PostgreSQL + POSTGRES_DB: dataprocessing # Name der Datenbank die erstellt wird + POSTGRES_USER: postgres # Benutzername + POSTGRES_PASSWORD: password # 🔐 Passwort (in Produktion geheimer!) + volumes: + - postgres_data:/var/lib/postgresql/data # 💾 Daten persistent speichern + - ./db_init:/docker-entrypoint-initdb.d # 📂 Optional: SQL-Skripts beim Start + ports: + - "5432:5432" # Port freigeben (Host:Container) + networks: + - app_network # 🌐 Internes Netzwerk für Container-Kommunikation + + # 🐍 CONTAINER 2: Unsere Python-Anwendung + python_app: + build: . # 🏗️ Baue Container aus Dockerfile in diesem Verzeichnis + environment: # Diese Variablen kann unser Python-Code lesen + DB_HOST: postgres # ❗ WICHTIG: Name des DB-Containers (nicht localhost!) + DB_PORT: 5432 + DB_NAME: dataprocessing + DB_USER: postgres + DB_PASSWORD: password + volumes: # 📂 Verbinde Host-Verzeichnisse mit Container + - ./input:/app/input:ro # Host ./input → Container /app/input (read-only) + - ./output:/app/output # Host ./output → Container /app/output (read-write) + depends_on: # ⏱️ Warte bis postgres-Container läuft + - postgres + networks: + - app_network # 🌐 Gleiches Netzwerk = können miteinander sprechen + restart: unless-stopped # 🔄 Automatisch neu starten bei Absturz + + # 🌐 CONTAINER 3: pgAdmin (Web-Interface für PostgreSQL) + pgadmin: + image: dpage/pgadmin4:8 + environment: + PGADMIN_DEFAULT_EMAIL: admin@example.com + PGADMIN_DEFAULT_PASSWORD: admin + ports: + - "8080:80" # 🌐 Zugriff via http://localhost:8080 + depends_on: + - postgres + networks: + - app_network + +# 💾 VOLUMES: Persistente Datenspeicherung +volumes: + postgres_data: # Docker verwaltet diesen Speicher automatisch + # 💡 Auch wenn Container gelöscht wird, bleiben Daten erhalten + +# 🌐 NETWORKS: Virtuelle Netzwerke für Container-Kommunikation +networks: + app_network: + driver: bridge # Standard-Netzwerk-Typ + # 💡 Alle Container in diesem Netzwerk können sich über Namen erreichen +``` + +**🤔 Warum docker-compose?** +- **Ohne compose:** `docker run postgres`, dann `docker run python_app` - sehr umständlich! +- **Mit compose:** Ein Befehl (`docker-compose up`) startet ALLES automatisch +- **Networks:** Container können sich über Namen finden (`postgres` statt IP-Adresse) +- **Volumes:** Daten gehen nicht verloren beim Container-Neustart + +--- + +## 🔧 .env - Geheime Konfiguration + +```env +# 🔐 Sensible Daten sollten NICHT in docker-compose.yml stehen +# Diese Datei wird von docker-compose automatisch gelesen + +# Datenbankverbindung +DB_HOST=postgres +DB_PORT=5432 +DB_NAME=dataprocessing +DB_USER=postgres +DB_PASSWORD=password # ❗ In Produktion: sicheres Passwort! + +# Python-Einstellungen +PYTHONPATH=/app +PYTHONUNBUFFERED=1 +``` + +**💡 Wichtig:** Die `.env`-Datei niemals in Git committen! (→ `.gitignore`) + +--- + +## 📊 Beispiel-Daten + +### **input/sample_data.csv** +```csv +id,name,value,category +1,Item A,10,electronics +2,Item B,25,clothing +3,Item C,15,electronics +4,Item D,30,books +5,Item E,8,clothing +``` + +**💡 Das ist eine normale CSV-Datei auf Deinem Host-PC** +- Liegt in `./input/sample_data.csv` +- Wird in den Container als `/app/input/sample_data.csv` "gemountet" +- Unser Python-Code kann sie lesen, als wäre sie im Container + +--- + +## 🚀 Schritt-für-Schritt Anleitung + +### **1. Projekt erstellen** +```bash +# Verzeichnis erstellen +mkdir python-docker-project +cd python-docker-project + +# Struktur erstellen +mkdir -p app input output +touch requirements.txt Dockerfile docker-compose.yml .env +touch app/__init__.py app/main.py app/data_processor.py app/database.py +``` + +### **2. Code schreiben** +- Alle Dateien wie oben gezeigt erstellen und befüllen + +### **3. Container bauen und starten** +```bash +# Alle Container bauen und starten +docker-compose up --build + +# 🔍 Was passiert: +# 1. Docker baut unseren Python-Container (aus Dockerfile) +# 2. Lädt PostgreSQL-Image herunter +# 3. Lädt pgAdmin-Image herunter +# 4. Erstellt Netzwerk "app_network" +# 5. Startet postgres-Container +# 6. Startet python_app-Container (wartet auf postgres) +# 7. Startet pgAdmin-Container +``` + +### **4. Überprüfen ob alles läuft** +```bash +# Laufende Container anzeigen +docker-compose ps + +# Logs ansehen +docker-compose logs python_app +docker-compose logs postgres + +# In pgAdmin einloggen: http://localhost:8080 +# Email: admin@example.com, Passwort: admin +``` + +### **5. Neue Daten verarbeiten** +```bash +# Neue CSV-Datei ins input-Verzeichnis kopieren +cp neue_daten.csv input/ + +# Python-App neu starten um neue Dateien zu verarbeiten +docker-compose restart python_app + +# Ergebnis ansehen +ls -la output/ +``` + +### **6. System stoppen** +```bash +# Alle Container stoppen +docker-compose down + +# Container stoppen UND Daten löschen (Vorsicht!) +docker-compose down -v +``` + +--- + +## 🔍 Docker-Befehle erklärt + +### **Grundlegende Container-Befehle** +```bash +# 📋 Alle laufenden Container anzeigen +docker ps + +# 📋 Alle Container anzeigen (auch gestoppte) +docker ps -a + +# 🔍 Container-Logs ansehen +docker logs + +# 🔑 In laufenden Container "einsteigen" +docker exec -it bash + +# 🗑️ Container stoppen +docker stop + +# 🗑️ Container löschen +docker rm +``` + +### **Image-Befehle** +```bash +# 📋 Alle Images anzeigen +docker images + +# 🏗️ Image aus Dockerfile bauen +docker build -t mein-python-app . + +# 🗑️ Image löschen +docker rmi + +# 🧹 Unbenutzte Images löschen +docker image prune +``` + +### **docker-compose-Befehle** +```bash +# 🚀 Alle Services starten +docker-compose up + +# 🚀 Im Hintergrund starten +docker-compose up -d + +# 🏗️ Images neu bauen und starten +docker-compose up --build + +# 🔄 Einzelnen Service neu starten +docker-compose restart python_app + +# 📋 Status aller Services +docker-compose ps + +# 🔍 Logs aller Services +docker-compose logs + +# 🔍 Logs eines bestimmten Service +docker-compose logs python_app + +# 📈 Live-Logs verfolgen +docker-compose logs -f python_app + +# 🔑 In Container einsteigen +docker-compose exec python_app bash +docker-compose exec postgres psql -U postgres -d dataprocessing + +# ⏹️ Alle Services stoppen +docker-compose down + +# 🗑️ Services stoppen und Volumes löschen +docker-compose down -v +``` + +--- + +## 🌟 Die wichtigsten Docker-Konzepte + +### **1. Images vs Container** +- **Image** = "Bauplan" (wie ein Kuchenrezept) +- **Container** = "Laufende Instanz" (wie ein gebackener Kuchen) +- Ein Image kann viele Container erstellen + +### **2. Volumes** +```yaml +volumes: + - ./input:/app/input # Host-Verzeichnis → Container-Verzeichnis +``` +- **Warum?** Container-Dateisystem ist temporär +- **Volume** = persistenter Speicher der überlebt + +### **3. Networks** +- Container in gleichem Netzwerk können sich über Namen erreichen +- `python_app` kann `postgres` kontaktieren (nicht IP-Adresse!) + +### **4. Environment Variables** +```yaml +environment: + DB_HOST: postgres # Diese Variable kann Python-Code lesen +``` + +### **5. Ports** +```yaml +ports: + - "8080:80" # Host-Port : Container-Port +``` +- Container-Port 80 wird auf Host-Port 8080 freigegeben +- Zugriff: `http://localhost:8080` + +--- + +## ❓ Häufige Anfänger-Probleme + +### **Problem 1: "Connection refused" zur Datenbank** +``` +❌ FALSCH: DB_HOST=localhost +✅ RICHTIG: DB_HOST=postgres +``` +- In Docker ist `localhost` der Container selbst +- Verwende den Service-Namen aus `docker-compose.yml` + +### **Problem 2: "File not found"** +``` +❌ FALSCH: input_dir = Path("./input") +✅ RICHTIG: input_dir = Path("/app/input") +``` +- Pfade sind INSIDE dem Container, nicht auf dem Host + +### **Problem 3: "Module not found"** +``` +❌ FALSCH: Umgebungsvariable vergessen +✅ RICHTIG: ENV PYTHONPATH=/app in Dockerfile +``` + +### **Problem 4: Änderungen nicht sichtbar** +```bash +# Nach Code-Änderungen Container neu bauen: +docker-compose up --build +``` + +### **Problem 5: Port bereits belegt** +``` +❌ Error: Port 5432 already in use +✅ Lösung: Anderen Port verwenden: "5433:5432" +``` + +--- + +## 🎯 Zusammenfassung - Was macht was? + +| Datei/Komponente | Was es macht | Warum wichtig | +|------------------|--------------|---------------| +| **Dockerfile** | "Bauanleitung" für Python-Container | Definiert was IN den Container kommt | +| **docker-compose.yml** | Orchestriert mehrere Container | Ein Befehl startet alles | +| **requirements.txt** | Liste der Python-Pakete | Automatische Installation | +| **.env** | Geheime Konfiguration | Passwörter nicht in Code | +| **volumes** | Datenaustausch Host ↔ Container | Input/Output-Dateien | +| **networks** | Container-Kommunikation | python_app kann postgres erreichen | +| **ports** | Zugriff von außen | Web-Interface erreichbar | + +**🚀 Mit einem Befehl hast Du:** +- ✅ Python-Umgebung mit allen Paketen +- ✅ PostgreSQL-Datenbank +- ✅ Web-Interface für DB +- ✅ Automatische File-Verarbeitung +- ✅ Persistente Datenspeicherung + +**Das ist die Macht von Docker! 🐳** \ No newline at end of file diff --git a/Computerkram/JavaScript/JavaScript Tutorial.md b/Computerkram/JavaScript/JavaScript Tutorial.md new file mode 100644 index 0000000..613328d --- /dev/null +++ b/Computerkram/JavaScript/JavaScript Tutorial.md @@ -0,0 +1,740 @@ +```markdown +--- +title: JavaScript Tutorial (für Python-Erfahrene) +tags: [javascript, tutorial, beginner, programming] +created: 2026-03-27 +--- + +# JavaScript Tutorial (für Python-Erfahrene) + +Ziel: Du lernst JavaScript von Grund auf, aber mit Fokus auf das, was du als Python-Erfahrener schnell einordnen kannst. Viele Beispiele sind so gestaltet, dass du sie 1:1 nachbauen und variieren kannst. + +--- + +## Inhaltsverzeichnis +1. [[#0 Wie führe ich JavaScript am besten aus]] +2. [[#1 Grundsyntax & Variablen]] +3. [[#2 Datentypen, Equality, Truthy/Falsy]] +4. [[#3 Strings & Template Literals]] +5. [[#4 Arrays (Listen) & Methoden]] +6. [[#5 Objekte (Dictionaries) & JSON]] +7. [[#6 Kontrollfluss (if, switch, Schleifen)]] +8. [[#7 Funktionen (inkl. Arrow Functions)]] +9. [[#8 Scope, Hoisting, Closures]] +10. [[#9 Module (import/export)]] +11. [[#10 Klassen & Prototypen]] +12. [[#11 Fehlerbehandlung (try/catch)]] +13. [[#12 Asynchronität: Event Loop, Promises, async/await]] +14. [[#13 DOM: Webseiten manipulieren]] +15. [[#14 Events (Click, Input, Delegation)]] +16. [[#15 Fetch API (HTTP), APIs, JSON]] +17. [[#16 Praktische Mini-Projekte]] +18. [[#17 Tooling: npm, Vite, Linting (kurz)]] +19. [[#18 Cheatsheet: Python vs. JavaScript]] + +--- + +## 0) Wie führe ich JavaScript am besten aus? + +### Option A — Browser-Konsole (schnell zum Experimentieren) +1. Öffne eine Website (z. B. `about:blank`) +2. DevTools öffnen: + - Chrome/Edge: `F12` oder `Ctrl+Shift+I` + - macOS: `Cmd+Opt+I` +3. Tab **Console** → JavaScript eintippen. + +Beispiel: +```js +console.log("Hello JS!"); +``` + +**Pro:** sofortiges Feedback +**Contra:** nicht so gut für größere Projekte + +--- + +### Option B — HTML + ` + + +``` + +Öffne die Datei im Browser (Doppelklick) und dann DevTools → Console. + +--- + +### Option C — HTML + externes `.js` File (empfohlen) +Das ist die gängigste Lern- und Projektstruktur. + +`index.html`: +```html + + + + + JS Tutorial + + + +

Hallo JavaScript

+ + + +``` + +`main.js`: +```js +console.log("main.js geladen"); + +document.querySelector("#btn").addEventListener("click", () => { + console.log("Button geklickt"); +}); +``` + +**Wichtig:** `defer` sorgt dafür, dass das HTML zuerst geparst wird, bevor dein JS läuft (sehr praktisch für DOM-Skripte). + +--- + +### Option D — Node.js (JavaScript außerhalb des Browsers) +Installiere Node.js (LTS). Dann im Terminal: + +```bash +node -v +node +``` + +Oder Datei: +`app.js`: +```js +console.log("Hallo aus Node!"); +``` + +Run: +```bash +node app.js +``` + +**Merke:** Browser-JS hat DOM/Web-APIs, Node hat dafür File-System etc. + +--- + +## 1) Grundsyntax & Variablen + +### `let`, `const`, (vermeide `var`) +```js +let x = 10; // kann neu zugewiesen werden +x = 11; + +const y = 20; // darf nicht neu zugewiesen werden +// y = 21; // TypeError + +const obj = { a: 1 }; +obj.a = 2; // erlaubt! (Objektinhalt mutiert) +// obj = { a: 3 }; // nicht erlaubt (Neuzuweisung) +``` + +**Python-Vergleich:** `const` ist kein echtes Immutable wie `tuple`, sondern verhindert nur Reassignment der Variable. + +--- + +## 2) Datentypen, Equality, Truthy/Falsy + +### Primitive Typen +- `number` (integers + floats) +- `string` +- `boolean` +- `undefined` +- `null` +- `bigint` +- `symbol` + +```js +let a; // undefined +let b = null; // absichtlich "leer" +``` + +### `==` vs `===` (wichtig) +- `===` vergleicht **ohne** Typumwandlung → nutze das fast immer +- `==` macht implizite Konvertierung → vermeide für Anfänger + +```js +0 == false // true (komisch) +0 === false // false (gut/strikt) + +"5" == 5 // true +"5" === 5 // false +``` + +### Truthy / Falsy +Falsy sind u. a.: `false`, `0`, `""`, `null`, `undefined`, `NaN` + +```js +if ("") console.log("läuft nicht"); +if ("0") console.log("läuft"); // nicht leerer String ist truthy +``` + +--- + +## 3) Strings & Template Literals + +```js +const name = "Ada"; +const age = 30; + +console.log("Hallo " + name + ", du bist " + age); +console.log(`Hallo ${name}, du bist ${age}`); // Template Literal +``` + +Nützliche String-Methoden: +```js +"Hello".toUpperCase(); // "HELLO" +" hi ".trim(); // "hi" +"abc".includes("b"); // true +"1,2,3".split(","); // ["1","2","3"] +``` + +--- + +## 4) Arrays (Listen) & Methoden + +```js +const nums = [1, 2, 3]; +nums.push(4); // [1,2,3,4] +nums.pop(); // entfernt letztes +nums[0]; // 1 +``` + +### Iteration +```js +for (const n of nums) { + console.log(n); +} +``` + +### `map`, `filter`, `reduce` (sehr wichtig) +```js +const doubled = nums.map(n => n * 2); // [2,4,6] +const evens = nums.filter(n => n % 2 === 0); // [2] +const sum = nums.reduce((acc, n) => acc + n, 0); // 6 +``` + +**Python-Vergleich:** `map/filter/reduce` ähnlich, aber in JS extrem häufig in UI/Frontend. + +--- + +## 5) Objekte (Dictionaries) & JSON + +### Objekte (Key-Value) +```js +const user = { + name: "Ada", + age: 30, + isAdmin: true +}; + +console.log(user.name); +console.log(user["age"]); +``` + +### Dynamische Keys +```js +const key = "score"; +const obj = { [key]: 42 }; +console.log(obj.score); // 42 +``` + +### Object Destructuring +```js +const { name, age } = user; +console.log(name, age); +``` + +### Spread (Kopieren/Mergen) +```js +const a = { x: 1, y: 2 }; +const b = { ...a, y: 999, z: 3 }; // {x:1,y:999,z:3} +``` + +### JSON +```js +const json = JSON.stringify(user); +const parsed = JSON.parse(json); +``` + +--- + +## 6) Kontrollfluss (if, switch, Schleifen) + +```js +const n = 7; + +if (n > 10) { + console.log("groß"); +} else if (n > 5) { + console.log("mittel"); +} else { + console.log("klein"); +} +``` + +### `switch` +```js +const role = "admin"; + +switch (role) { + case "admin": + console.log("Alles erlaubt"); + break; + case "user": + console.log("Standardrechte"); + break; + default: + console.log("Unbekannt"); +} +``` + +### Schleifen +```js +for (let i = 0; i < 3; i++) console.log(i); + +let i = 0; +while (i < 3) { + console.log(i); + i++; +} +``` + +--- + +## 7) Funktionen (inkl. Arrow Functions) + +### Funktionsdeklaration +```js +function add(a, b) { + return a + b; +} +``` + +### Function Expression +```js +const add2 = function (a, b) { + return a + b; +}; +``` + +### Arrow Function +```js +const add3 = (a, b) => a + b; +``` + +### Default-Parameter +```js +function greet(name = "Welt") { + return `Hallo ${name}`; +} +``` + +### Rest-Parameter +```js +function sum(...nums) { + return nums.reduce((acc, n) => acc + n, 0); +} +sum(1, 2, 3); // 6 +``` + +--- + +## 8) Scope, Hoisting, Closures + +### Block-Scope: `let/const` +```js +if (true) { + let x = 1; +} +// console.log(x); // ReferenceError +``` + +### Hoisting (vereinfachte Regel) +- `var` wird “hochgezogen” → vermeiden +- `let/const` existieren zwar “vorher”, sind aber in der **Temporal Dead Zone** → besser/strikter + +### Closure +```js +function makeCounter() { + let count = 0; + return function () { + count++; + return count; + }; +} + +const c = makeCounter(); +c(); // 1 +c(); // 2 +``` + +**Python-Vergleich:** ähnlich wie inner functions mit captured variables. + +--- + +## 9) Module (import/export) + +**Browser-Module**: In HTML: +```html + +``` + +`math.js`: +```js +export function add(a, b) { + return a + b; +} + +export const PI = 3.14159; +``` + +`main.js`: +```js +import { add, PI } from "./math.js"; + +console.log(add(2, 3)); +console.log(PI); +``` + +--- + +## 10) Klassen & Prototypen + +### Klasse +```js +class User { + constructor(name) { + this.name = name; + } + + greet() { + return `Hi ${this.name}`; + } +} + +const u = new User("Ada"); +console.log(u.greet()); +``` + +### Vererbung +```js +class Admin extends User { + constructor(name) { + super(name); + this.role = "admin"; + } +} + +const a = new Admin("Grace"); +``` + +**Merke:** JS ist prototyp-basiert; `class` ist syntactic sugar. + +--- + +## 11) Fehlerbehandlung (try/catch) + +```js +try { + JSON.parse("{ broken"); +} catch (err) { + console.error("Parsing fehlgeschlagen:", err.message); +} finally { + console.log("läuft immer"); +} +``` + +Eigene Fehler: +```js +function requirePositive(n) { + if (n <= 0) throw new Error("n muss > 0 sein"); + return n; +} +``` + +--- + +## 12) Asynchronität: Event Loop, Promises, async/await + +### Warum async? +Im Browser soll UI nicht blockieren. In Node geht’s um I/O. + +### Promise Basics +```js +const p = new Promise((resolve, reject) => { + setTimeout(() => resolve("fertig"), 500); +}); + +p.then(value => console.log(value)); +``` + +### `async/await` (empfohlen) +```js +function wait(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +async function run() { + console.log("start"); + await wait(300); + console.log("nach 300ms"); +} + +run(); +``` + +### Parallel vs. sequenziell +```js +async function parallel() { + const p1 = wait(200); + const p2 = wait(300); + await Promise.all([p1, p2]); + console.log("beide fertig"); +} +``` + +--- + +## 13) DOM: Webseiten manipulieren + +### Elemente finden +```js +const h1 = document.querySelector("h1"); +const items = document.querySelectorAll("li"); +``` + +### Text/HTML ändern +```js +h1.textContent = "Neuer Titel"; +h1.innerHTML = "Kursiv"; // vorsichtig (XSS bei fremden Daten!) +``` + +### Klassen und Styles +```js +h1.classList.add("highlight"); +h1.style.color = "tomato"; +``` + +### Elemente erstellen & anhängen +```js +const ul = document.querySelector("ul"); +const li = document.createElement("li"); +li.textContent = "Neues Item"; +ul.appendChild(li); +``` + +--- + +## 14) Events (Click, Input, Delegation) + +`index.html`: +```html + + +
+``` + +`main.js`: +```js +const input = document.querySelector("#name"); +const btn = document.querySelector("#save"); +const out = document.querySelector("#out"); + +btn.addEventListener("click", () => { + out.textContent = `Hallo ${input.value}`; +}); +``` + +### Event Delegation (praktisch bei Listen) +```js +document.querySelector("#list").addEventListener("click", (e) => { + if (e.target.matches("li")) { + console.log("geklickt:", e.target.textContent); + } +}); +``` + +--- + +## 15) Fetch API (HTTP), APIs, JSON + +### GET Request +```js +async function loadTodo() { + const res = await fetch("https://jsonplaceholder.typicode.com/todos/1"); + if (!res.ok) throw new Error(`HTTP ${res.status}`); + + const data = await res.json(); + console.log(data); +} + +loadTodo().catch(console.error); +``` + +### POST Request +```js +async function createPost() { + const res = await fetch("https://jsonplaceholder.typicode.com/posts", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ title: "Hi", body: "Text", userId: 1 }) + }); + + const data = await res.json(); + console.log("created:", data); +} +``` + +--- + +## 16) Praktische Mini-Projekte + +### Projekt 1: Counter +`index.html`: +```html +

0

+ + + + +``` + +`main.js`: +```js +let count = 0; + +const el = document.querySelector("#count"); +const render = () => (el.textContent = String(count)); + +document.querySelector("#inc").addEventListener("click", () => { + count++; + render(); +}); +document.querySelector("#dec").addEventListener("click", () => { + count--; + render(); +}); +document.querySelector("#reset").addEventListener("click", () => { + count = 0; + render(); +}); + +render(); +``` + +### Projekt 2: Todo-Liste (minimal) +`index.html`: +```html + + +
    + +``` + +`main.js`: +```js +const input = document.querySelector("#todo"); +const btn = document.querySelector("#add"); +const list = document.querySelector("#list"); + +btn.addEventListener("click", () => { + const text = input.value.trim(); + if (!text) return; + + const li = document.createElement("li"); + li.textContent = text; + list.appendChild(li); + + input.value = ""; + input.focus(); +}); + +// Klick zum Entfernen (Delegation) +list.addEventListener("click", (e) => { + if (e.target.matches("li")) e.target.remove(); +}); +``` + +--- + +## 17) Tooling: npm, Vite, Linting (kurz) + +Wenn du über “nur HTML+JS” hinaus willst (Module, Bundling, Dev-Server): + +### Vite Setup +```bash +npm create vite@latest my-app +cd my-app +npm install +npm run dev +``` + +Das erstellt ein modernes Dev-Setup mit Hot Reload. + +### Linting (optional) +- ESLint hilft, typische Fehler früh zu finden. +- Prettier formatiert Code automatisch. + +--- + +## 18) Cheatsheet: Python vs. JavaScript + +### Datenstrukturen +- Python `list` ≈ JS `Array` +- Python `dict` ≈ JS `Object` oder `Map` +- Python `None` ≈ JS `null` (oder `undefined` je nach Kontext) + +### Funktionen +- Python: `def f(a=1): ...` +- JS: `function f(a = 1) { ... }` oder `(a = 1) => ...` + +### Strings +- Python: `f"{x}"` +- JS: `` `${x}` `` + +### Imports +- Python: `import x` +- JS (ESM): `import x from "./x.js"` / `import {a} from ...` + +### Iteration +- Python: `for x in xs:` +- JS: `for (const x of xs) { ... }` + +### Async +- Python: `async def`, `await` +- JS: `async function`, `await` (sehr ähnlich im Feeling, andere Runtime-Details) + +--- + +## Nächste Schritte (Empfehlung) +1. Baue die Mini-Projekte nach und verändere sie (z. B. Todo: “erledigt” toggle statt löschen). +2. Übe `map/filter/reduce` auf Arrays mit echten Daten (z. B. aus `fetch`). +3. Wenn du Web-Apps willst: lerne danach ein Framework (React/Vue/Svelte) – aber erst, wenn DOM + async sitzen. + +--- + +## Offene Fragen (damit ich das Tutorial besser anpassen kann) +- Willst du primär **Frontend im Browser** lernen oder auch **Node.js Backend**? +- Arbeitest du lieber mit **Vanilla JS** (ohne Framework) oder willst du schnell Richtung **React/Vue**? +``` + +Wenn du willst, kann ich daraus auch mehrere Obsidian-Notizen machen (z. B. „JS Basics“, „DOM“, „Async“, „Mini-Projekte“) und dir eine sinnvolle Link-Struktur (MOC) anlegen. \ No newline at end of file diff --git a/Computerkram/KI Prompt Templates/Notiz (anbei) überarbeiten.md b/Computerkram/KI Prompt Templates/Notiz (anbei) überarbeiten.md new file mode 100644 index 0000000..c8aef54 --- /dev/null +++ b/Computerkram/KI Prompt Templates/Notiz (anbei) überarbeiten.md @@ -0,0 +1,6 @@ +Anbei ist eine Notiz zu ==\==. +Bitte prüfe dieses Dokument: +* Korrigiere Fehler +* Ergänzen fehlende Infos +* Stelle sicher, dass das Dokument gut lesbar ist und wesentliche Infos schnell erfasst werden können +* Lege Links zu wichtigen Themen an, die z.B von Obsidian als solche erkannt werden (Bsp. "bla bla [[wichtiges Thema]] bla")(diese kann ich dann bei Gelegenheit später mit Inhalt füllen) \ No newline at end of file diff --git a/Computerkram/LibrechatAI.md b/Computerkram/LibrechatAI.md new file mode 100644 index 0000000..34c77ba --- /dev/null +++ b/Computerkram/LibrechatAI.md @@ -0,0 +1 @@ +https://www.librechat.ai/ diff --git a/Computerkram/Linux/AppImage Programme einrichten.md b/Computerkram/Linux/AppImage Programme einrichten.md new file mode 100644 index 0000000..8fb8290 --- /dev/null +++ b/Computerkram/Linux/AppImage Programme einrichten.md @@ -0,0 +1,164 @@ +Unten eine vollständige, schrittweise Anleitung (auf Deutsch), wie du eine AppImage unter /opt ablegst, ins Startmenü einbindest und optional ein Icon extrahierst. Ich gebe dir Beispielbefehle — ersetze die Platzhalter durch den echten Dateinamen/deine App-Namen. + +Voraussetzungen +- Du brauchst sudo-Rechte. +- AppImage-Datei (z. B. ExampleApp.AppImage) ist im Downloads-Ordner. + +Schritt 1 — AppImage ausführbar machen +Öffne ein Terminal und mache die Datei ausführbar: +``` +cd ~/Downloads +chmod +x ExampleApp.AppImage +``` + +Schritt 2 — AppImage nach /opt verschieben +Erstelle ein Unterverzeichnis unter /opt (z. B. /opt/exampleapp) und verschiebe die AppImage dort hin: +``` +sudo mkdir -p /opt/exampleapp +sudo mv ExampleApp.AppImage /opt/exampleapp/ +sudo chown -R root:root /opt/exampleapp +``` +Optional: Um den Namen konsistent zu halten, kannst du die Datei umbenennen: +``` +sudo mv /opt/exampleapp/ExampleApp.AppImage /opt/exampleapp/exampleapp.AppImage +``` + +Schritt 3 — Einfachen Startbefehl anlegen (Symlink oder Wrapper) +Damit die App systemweit mit kurzem Namen startet, lege einen Symlink oder ein kleines Wrapper-Skript in /usr/local/bin an. + +Variante A — Symlink: +``` +sudo ln -s /opt/exampleapp/exampleapp.AppImage /usr/local/bin/exampleapp +sudo chmod +x /usr/local/bin/exampleapp +``` + +Variante B — Wrapper-Skript (empfohlen, falls Argumente weitergeleitet werden sollen): +``` +sudo tee /usr/local/bin/exampleapp > /dev/null <<'EOF' +#!/bin/sh +exec /opt/exampleapp/exampleapp.AppImage "$@" +EOF +sudo chmod +x /usr/local/bin/exampleapp +``` + +Schritt 4 — Icon aus dem AppImage extrahieren (optional, aber empfohlen) +Viele AppImages haben ein eingebettetes Icon (.DirIcon) oder eine .png-Datei. So extrahierst du es: +``` +cd /tmp +/opt/exampleapp/exampleapp.AppImage --appimage-extract +# die extrahierten Dateien liegen jetzt in /tmp/squashfs-root +``` +Suche das Icon: +``` +ls squashfs-root | grep -i DirIcon || ls squashfs-root | grep -i png +``` +Beispiel: wenn squashfs-root/.DirIcon vorhanden ist, kopiere es als PNG in die Icon-Hierarchie: +``` +sudo mkdir -p /usr/share/icons/hicolor/256x256/apps +sudo cp squashfs-root/.DirIcon /usr/share/icons/hicolor/256x256/apps/exampleapp.png +sudo chmod 644 /usr/share/icons/hicolor/256x256/apps/exampleapp.png +``` +(Optional) Icon-Cache aktualisieren: +``` +sudo gtk-update-icon-cache /usr/share/icons/hicolor +``` +Aufräumen: +``` +rm -rf /tmp/squashfs-root +``` + +Hinweis: Wenn du die App nur für deinen Benutzer installierst, kopiere das Icon nach ~/.local/share/icons/hicolor/256x256/apps/ statt /usr/share/... + +Schritt 5 — .desktop-Datei anlegen (Startmenü-Eintrag) +Siehe auch hier: [[Linux .desktop Dateien]] +Systemweit (für alle Benutzer): +``` +sudo tee /usr/share/applications/exampleapp.desktop > /dev/null <<'EOF' +[Desktop Entry] +Name=ExampleApp +GenericName=Example Application +Comment=Beschreibung der Anwendung +Exec=/usr/local/bin/exampleapp %U +Icon=exampleapp +Terminal=false +Type=Application +Categories=Utility;Application; +StartupWMClass=ExampleApp +EOF +``` + +Alternativ für nur deinen Benutzer: +``` +mkdir -p ~/.local/share/applications +tee ~/.local/share/applications/exampleapp.desktop > /dev/null <<'EOF' +[Desktop Entry] +Name=ExampleApp +GenericName=Example Application +Comment=Beschreibung der Anwendung +Exec=/usr/local/bin/exampleapp %U +Icon=/home/deinuser/.local/share/icons/hicolor/256x256/apps/exampleapp.png +Terminal=false +Type=Application +Categories=Utility;Application; +StartupWMClass=ExampleApp +EOF +``` +Wichtige Felder: +- Exec: Pfad zur ausführbaren Datei oder zu deinem Symlink (/usr/local/bin/exampleapp). %U erlaubt URLs/Dateien als Argumente. +- Icon: entweder der einfache Icon-Name (ohne Endung), wenn du das Icon in /usr/share/icons/hicolor abgelegt hast, oder ein voller Pfad. +- Categories: für die Kategorisierung im Menü (z. B. Utility, Development, Office). +- Terminal=false, falls kein Terminal nötig. + +Setze die richtigen Rechte: +``` +sudo chmod 644 /usr/share/applications/exampleapp.desktop +# oder für user: +chmod 644 ~/.local/share/applications/exampleapp.desktop +``` + +Schritt 6 — Desktop-Datenbank aktualisieren (falls nötig) +Für Systemmenüs: +``` +sudo update-desktop-database +``` +Für GNOME/andere DEs: in der Regel reicht Aus- und Einloggen oder Neustart des Shells/Session. + +Schritt 7 — Testen +- Öffne dein Startmenü / Activities und suche nach "ExampleApp". +- Alternativ im Terminal: `exampleapp` (oder `/opt/exampleapp/exampleapp.AppImage`). + +Optionale Hinweise +- Automatische Updates: Manche AppImages unterstützen AppImageUpdate (z. B. mit zsync) oder du kannst AppImageLauncher verwenden, das AppImage-Integration & Updates verwaltet. +- Sicherheitsaspekt: AppImages laufen nicht automatisch in einem Sandbox; für zusätzliche Isolation kannst du firejail verwenden. +- Entfernen: Entferne /opt/exampleapp, den Symlink und die .desktop/Icons, um die App rückstandsfrei zu löschen. + +Kurzbeispiel (kompakt) +Angenommen Datei heißt ExampleApp.AppImage in ~/Downloads und dein Benutzername ist user: +``` +cd ~/Downloads +chmod +x ExampleApp.AppImage +sudo mkdir -p /opt/exampleapp +sudo mv ExampleApp.AppImage /opt/exampleapp/exampleapp.AppImage +sudo ln -s /opt/exampleapp/exampleapp.AppImage /usr/local/bin/exampleapp +# Icon extrahieren (falls vorhanden) +/opt/exampleapp/exampleapp.AppImage --appimage-extract +sudo cp squashfs-root/.DirIcon /usr/share/icons/hicolor/256x256/apps/exampleapp.png +rm -rf squashfs-root +# .desktop anlegen +sudo tee /usr/share/applications/exampleapp.desktop > /dev/null <<'EOF' +[Desktop Entry] +Name=ExampleApp +Exec=/usr/local/bin/exampleapp %U +Icon=exampleapp +Terminal=false +Type=Application +Categories=Utility; +EOF +sudo chmod 644 /usr/share/applications/exampleapp.desktop +sudo update-desktop-database +``` + +Wenn du willst, schreibe mir: +- Wie die AppImage-Datei heißt, und +- ob du die Installation systemweit (für alle Benutzer) oder nur für dich wünschst. +Dann passe ich die Befehle genau für deine App an. \ No newline at end of file diff --git a/Computerkram/Linux/BASH Basics/BASH Basics.md b/Computerkram/Linux/BASH Basics/BASH Basics.md new file mode 100644 index 0000000..4a4dd98 --- /dev/null +++ b/Computerkram/Linux/BASH Basics/BASH Basics.md @@ -0,0 +1,40 @@ +# BASH Basics - Übersicht + +Sammlung wichtiger BASH-Befehle und Konzepte für die Linux-Konsole. + +## Grundlegende Konzepte + +- [[BASH Funktionen]] - Wiederverwendbare Funktionen erstellen + +## Dateiverwaltung + +- [[ls]] - Dateien auflisten und Größen anzeigen +- [[find]] - Dateien suchen, filtern und verarbeiten (inkl. Datum, Löschen) +- [[Symlinks]] - Symbolische Links erstellen und verwalten + +## Textverarbeitung + +- [[grep]] - Textsuche in Dateien +- [[sed]] - Stream-Editor für Textmanipulation +- [[awk]] - Datenextraktion und Spaltenverarbeitung + +## Berechtigungen + +- [[Dateiberechtigungen]] - chmod und chown (Rechte, Eigentümer, Gruppen) + +## Archive und Backup + +- [[tar]] - Archive erstellen/entpacken und Software installieren +- [[rsync]] - Dateien synchronisieren + +## System + +- [[lsblk]] - Block-Geräte anzeigen +- [[fstab Credentials]] - Zugangsdaten sicher in fstab speichern + +## Verwandte Themen + +Weitere Linux-Themen im übergeordneten Verzeichnis: +- [[Linux]] - Allgemeine Linux-Dokumentation +- [[SSH Verbindung in Linux]] - SSH-Verbindungen +- [[Navidrome]] - Musik-Server diff --git a/Computerkram/Linux/BASH Basics/BASH Funktionen.md b/Computerkram/Linux/BASH Basics/BASH Funktionen.md new file mode 100644 index 0000000..31763ed --- /dev/null +++ b/Computerkram/Linux/BASH Basics/BASH Funktionen.md @@ -0,0 +1,693 @@ +# BASH Funktionen# BASH FunktionenIn **[[Bash]]** kannst du wiederverwendbare **Funktionen** definieren, um Code übersichtlicher und modularer zu gestalten. + + + +In BASH kannst du wiederverwendbare Funktionen definieren, um Code übersichtlicher und modularer zu gestalten.Hier ist eine kurze Einführung mit Beispielen 👇 + + + +## GrundsyntaxIn BASH kannst du wiederverwendbare Funktionen definieren, um Code übersichtlicher und modularer zu gestalten. + + + +```bash--- + +meine_funktion() { + + echo "Das ist eine wiederverwendbare Funktion!"## Grundsyntax + +} + +```### 🔹 **Grundsyntax einer Funktion** + + + +Alternative Syntax (weniger üblich):```bash + + + +```bashmeine_funktion() {```bash + +function meine_funktion { + + echo "Das ist eine wiederverwendbare Funktion!" echo "Das ist eine wiederverwendbare Funktion!"meine_funktion() { + +} + +```} echo "Das ist eine wiederverwendbare Funktion!" + + + +## Funktion mit Parametern```} + + + +In BASH werden Argumente positional übergeben: `$1`, `$2`, usw.``` + + + +```bashAlternative Syntax (weniger üblich): + +begruesse() { + + echo "Hallo $1!"Oder alternativ (weniger üblich, aber erlaubt): + +} + +```bash + +begruesse "Anna" + +# Ausgabe: Hallo Anna!function meine_funktion {```bash + +``` + + echo "Das ist eine wiederverwendbare Funktion!"function meine_funktion { + +## Rückgabewerte + +} echo "Das ist eine wiederverwendbare Funktion!" + +### Numerischer Exit-Code + +```} + +Eine Funktion kann mit `return` einen numerischen Exit-Code (0–255) zurückgeben: + +``` + +```bash + +teste_zahl() {## Funktion mit Parametern + + if (( $1 > 10 )); then + + return 0 # Erfolg--- + + else + + return 1 # FehlerIn BASH werden Argumente positional übergeben: `$1`, `$2`, usw. + + fi + +}### 🔹 **Funktion mit Parametern** + + + +if teste_zahl 15; then```bash + + echo "Größer als 10" + +elsebegruesse() {In Bash werden Argumente **positional** übergeben — also `$1`, `$2`, usw. + + echo "Nicht größer als 10" + +fi echo "Hallo $1!" + +``` + +}```bash + +### Text zurückgeben + +begruesse() { + +Um Text zurückzugeben, verwende `echo` oder `printf` und Command Substitution: + +begruesse "Anna" echo "Hallo $1!" + +```bash + +addiere() {# Ausgabe: Hallo Anna!} + + echo $(( $1 + $2 )) + +}``` + + + +summe=$(addiere 3 5)begruesse "Anna" + +echo "Summe: $summe" # Ausgabe: Summe: 8 + +```## Rückgabewerte# Ausgabe: Hallo Anna! + + + +## Funktionen wiederverwendbar machen``` + + + +Speichere Funktionen in einer separaten Datei und lade sie mit `source`:### Numerischer Exit-Code + + + +**funktionen.sh:**--- + +```bash + +#!/bin/bashEine Funktion kann mit `return` einen numerischen Exit-Code (0–255) zurückgeben: + +begruesse() { + + echo "Hallo $1!"### 🔹 **Rückgabewerte** + +} + +``````bash + + + +**hauptskript.sh:**teste_zahl() {- Eine Funktion kann mit `return` einen **numerischen Exit-Code** (0–255) zurückgeben. + +```bash + +#!/bin/bash if (( $1 > 10 )); then + +source ./funktionen.sh + + return 0 # Erfolg- Um Text zurückzugeben, verwendest du **`echo`** oder **`printf`** und fängst den Wert mit **Command Substitution** ein. + +begruesse "Welt" + +``` else + + + +Alternative: `. ./funktionen.sh` return 1 # Fehler + + + +## Lokale Variablen fi```bash + + + +Verwende `local`, um Variablen nur innerhalb der Funktion sichtbar zu machen:}# numerischer Rückgabewert + + + +```bashteste_zahl() { + +addiere() { + + local summe=$(( $1 + $2 ))if teste_zahl 15; then if (( $1 > 10 )); then + + echo "$summe" + +} echo "Größer als 10" return 0 # Erfolg + +``` + +else else + +## Default-Werte für Parameter + + echo "Nicht größer als 10" return 1 # Fehler + +```bash + +mein_script() {fi fi + + local name="${1:-Welt}" # Standardwert 'Welt' + + local sprache="${2:-de}" # Standardwert 'de'```} + + + + echo "Name: $name, Sprache: $sprache" + +} + +### Text zurückgebenif teste_zahl 15; then + +mein_script "Anna" "en" # Name: Anna, Sprache: en + +mein_script "Bob" # Name: Bob, Sprache: de echo "Größer als 10" + +``` + +Um Text zurückzugeben, verwende `echo` oder `printf` und Command Substitution:else + +## Benannte Argumente simulieren + + echo "Nicht größer als 10" + +### Mit case und Schleife + +```bashfi + +```bash + +begruesse() {addiere() {``` + + local name="Welt" + + local sprache="de" echo $(( $1 + $2 )) + + + + for arg in "$@"; do}```bash + + case $arg in + + --name=*)# Text zurückgeben + + name="${arg#*=}" + + ;;summe=$(addiere 3 5)addiere() { + + --sprache=*|--lang=*) + + sprache="${arg#*=}"echo "Summe: $summe" # Ausgabe: Summe: 8 echo $(( $1 + $2 )) + + ;; + + *)```} + + echo "Unbekannte Option: $arg" >&2 + + ;; + + esac + + done## Funktionen wiederverwendbar machensumme=$(addiere 3 5) + + + + echo "Hallo $name! (Sprache: $sprache)"echo "Summe: $summe" + +} + +Speichere Funktionen in einer separaten Datei und lade sie mit `source`:# Ausgabe: Summe: 8 + +begruesse --name=Anna --sprache=en + +`````` + + + +**Vorteile:****funktionen.sh:** + +- Reihenfolge der Argumente ist egal + +- Default-Werte bleiben bestehen```bash--- + +- Sehr gut lesbar + +#!/bin/bash + +### Mit assoziativem Array + +begruesse() {### 🔹 **Wiederverwendbar machen** + +```bash + +begruesse() { echo "Hallo $1!" + + declare -A args=( + + [name]="Welt"}Speichere deine Funktionen in einer separaten Datei, z. B. `funktionen.sh`, und **sourcen** sie in anderen Skripten: + + [sprache]="de" + + )``` + + + + for arg in "$@"; do**funktionen.sh** + + [[ $arg == *=* ]] || continue + + key="${arg%%=*}"**hauptskript.sh:** + + val="${arg#*=}" + + args[$key]="$val"```bash```bash + + done + +#!/bin/bash#!/bin/bash + + echo "Hallo ${args[name]}! (Sprache: ${args[sprache]})" + +}source ./funktionen.shbegruesse() { + + + +begruesse name=Anna sprache=en echo "Hallo $1!" + +``` + +begruesse "Welt"} + +## Praktische Beispiele + +`````` + +### Backup-Funktion + + + +```bash + +backup_datei() {Alternative: `. ./funktionen.sh`**hauptskript.sh** + + local datei="$1" + + local backup="${datei}.backup-$(date +%Y%m%d)" + + + + if [[ -f "$datei" ]]; then## Lokale Variablen```bash + + cp "$datei" "$backup" + + echo "Backup erstellt: $backup"#!/bin/bash + + else + + echo "Fehler: $datei nicht gefunden" >&2Verwende `local`, um Variablen nur innerhalb der Funktion sichtbar zu machen:source ./funktionen.sh + + return 1 + + fi + +} + +```bashbegruesse "Welt" + +backup_datei wichtig.txt + +```addiere() {``` + + + +### Fehlerbehandlung local summe=$(( $1 + $2 )) + + + +```bash echo "$summe"Oder mit: + +sicheres_loeschen() { + + local datei="$1"} + + + + if [[ ! -f "$datei" ]]; then``````bash + + echo "Fehler: $datei existiert nicht" >&2 + + return 1. ./funktionen.sh + + fi + + ## Default-Werte für Parameter``` + + read -p "Wirklich $datei löschen? (j/n) " antwort + + if [[ "$antwort" == "j" ]]; then + + rm "$datei" + + echo "$datei gelöscht"```bash--- + + else + + echo "Abgebrochen"mein_script() { + + fi + +} local name="${1:-Welt}" # Standardwert 'Welt'### 🔹 **Bonus: Funktionen mit lokaler Variable** + +``` + + local sprache="${2:-de}" # Standardwert 'de' + +### Mehrere Rückgabewerte + +Verwende `local`, um Variablen nur innerhalb der Funktion sichtbar zu machen: + +```bash + +datei_info() { echo "Name: $name, Sprache: $sprache" + + local datei="$1" + + }```bash + + if [[ -f "$datei" ]]; then + + echo "$(wc -l < "$datei")" # Zeilenaddiere() { + + echo "$(wc -w < "$datei")" # Wörter + + echo "$(stat -c%s "$datei")" # Größemein_script "Anna" "en" # Name: Anna, Sprache: en local summe=$(( $1 + $2 )) + + fi + +}mein_script "Bob" # Name: Bob, Sprache: de echo "$summe" + + + +# Verwendung```} + +read zeilen woerter groesse <<< $(datei_info text.txt) + +echo "Zeilen: $zeilen, Wörter: $woerter, Größe: $groesse"``` + +``` + +## Benannte Argumente simulieren + +## Best Practices + +--- + +### Eingabevalidierung + +### Mit case und Schleife + +```bash + +verarbeite_zahl() {## 🧩 Beispiel 1: Named Arguments via `local` + Parameter Expansion + + local zahl="$1" + + ```bash + + if ! [[ "$zahl" =~ ^[0-9]+$ ]]; then + + echo "Fehler: Keine gültige Zahl" >&2begruesse() {```bash + + return 1 + + fi local name="Welt"mein_script() { + + + + echo "Ergebnis: $((zahl * 2))" local sprache="de" local name="${1:-Welt}" # Standardwert 'Welt' + +} + +``` local sprache="${2:-de}" # Standardwert 'de' + + + +### Dokumentation for arg in "$@"; do + + + +```bash case $arg in echo "Name: $name" + +# Berechnet die Summe zweier Zahlen + +# Parameter: --name=*) echo "Sprache: $sprache" + +# $1 - erste Zahl + +# $2 - zweite Zahl name="${arg#*=}"} + +# Rückgabe: + +# Summe der beiden Zahlen ;; + +addiere() { + + echo $(( $1 + $2 )) --sprache=*|--lang=*)mein_script "Anna" "en" + +} + +``` sprache="${arg#*=}"mein_script "Bob" + + + +### Fehler propagieren ;;``` + + + +```bash *) + +hauptfunktion() { + + hilfsfunktion || return $? echo "Unbekannte Option: $arg" >&2➡️ Ausgabe: + + # Weiterer Code nur wenn hilfsfunktion erfolgreich + +} ;; + +``` + + esac``` + +## Siehe auch + + doneName: Anna + +- [[grep]] - Textsuche in Scripten + +- [[sed]] - Textmanipulation in FunktionenSprache: en + +- [[find]] - Dateien in Funktionen verarbeiten + + echo "Hallo $name! (Sprache: $sprache)"Name: Bob + +}Sprache: de + +``` + +begruesse --name=Anna --sprache=en + +```Aber das sind **positionsbasierte Argumente**, keine echten "benannten". + + + +**Vorteile:**--- + +- Reihenfolge der Argumente ist egal + +- Default-Werte bleiben bestehen## 🧩 Beispiel 2: Simulierte **benannte Argumente** mit `case` oder Schleife + +- Sehr gut lesbar + +Du kannst Argumente wie `--name=Anna` oder `--lang=en` verwenden: + +### Mit assoziativem Array + +```bash + +```bashbegruesse() { + +begruesse() { local name="Welt" + + declare -A args=( local sprache="de" + + [name]="Welt" + + [sprache]="de" for arg in "$@"; do + + ) case $arg in + + --name=*) + + for arg in "$@"; do name="${arg#*=}" + + [[ $arg == *=* ]] || continue ;; + + key="${arg%%=*}" --sprache=*|--lang=*) + + val="${arg#*=}" sprache="${arg#*=}" + + args[$key]="$val" ;; + + done *) + + echo "Unbekannte Option: $arg" >&2 + + echo "Hallo ${args[name]}! (Sprache: ${args[sprache]})" ;; + +} esac + + done + +begruesse name=Anna sprache=en + +``` echo "Hallo $name! (Sprache: $sprache)" + +} + +## Siehe auch + +begruesse --name=Anna --sprache=en + +- [[find]] - BASH-Befehl zum Suchen von Dateienbegruesse + +- [[grep]] - Textsuche in Dateien``` + + +➡️ Ausgabe: + +``` +Hallo Anna! (Sprache: en) +Hallo Welt! (Sprache: de) +``` + +✅ Vorteil: Reihenfolge der Argumente ist egal +✅ Default-Werte bleiben bestehen +✅ Sehr gut lesbar + +--- + +## 🧩 Beispiel 3: Named Args via **`declare -A` (assoziatives Array)** + +Etwas fortgeschrittener, aber elegant: + +```bash +begruesse() { + declare -A args=( + [name]="Welt" + [sprache]="de" + ) + + for arg in "$@"; do + [[ $arg == *=* ]] || continue + key="${arg%%=*}" + val="${arg#*=}" + args[$key]="$val" + done + + echo "Hallo ${args[name]}! (Sprache: ${args[sprache]})" +} + +begruesse name=Anna sprache=en +``` + +--- + +## 🧩 Beispiel 4: Default-Werte per `:`-Operator + +Falls du Parameter ohne Parsing willst, kannst du Default-Werte einfach so setzen: + +```bash +begruesse() { + local name="${1:-Welt}" + local sprache="${2:-de}" + + echo "Hallo $name in Sprache $sprache" +} +``` + +--- + +### 🔹 Empfehlung + +Wenn du Funktionen **häufig wiederverwenden** oder **CLI-ähnliche Aufrufe** unterstützen willst, ist **Variante 2 (mit `--option=wert`)** am besten: + +- Lesbar + +- Robust + +- Einfach erweiterbar + + +--- diff --git a/Computerkram/Linux/BASH Basics/Dateiberechtigungen.md b/Computerkram/Linux/BASH Basics/Dateiberechtigungen.md new file mode 100644 index 0000000..0e0cca0 --- /dev/null +++ b/Computerkram/Linux/BASH Basics/Dateiberechtigungen.md @@ -0,0 +1,365 @@ +# Dateiberechtigungen - chmod und chown + +Verwaltung von Zugriffsrechten, Eigentümern und Gruppen in Linux. + +## Rechte-System in Linux + +Jede Datei hat: +- **Eigentümer (Owner)** - der Benutzer, dem die Datei gehört +- **Gruppe (Group)** - eine Benutzergruppe +- **Zugriffsrechte** für drei Bereiche: + - **u** (user) = Eigentümer + - **g** (group) = Gruppe + - **o** (others) = Andere + +Jeder Bereich hat drei Rechte: +- **r** (read) = Lesen (4) +- **w** (write) = Schreiben (2) +- **x** (execute) = Ausführen (1) + +## Rechte anzeigen + +```bash +ls -l datei.txt +``` + +Ausgabe: +``` +-rw-r--r-- 1 alice developers 1234 Nov 7 10:00 datei.txt +``` + +- Position 1: Dateityp (`-` = Datei, `d` = Verzeichnis, `l` = Link) +- Position 2-4: User-Rechte (`rw-`) +- Position 5-7: Group-Rechte (`r--`) +- Position 8-10: Other-Rechte (`r--`) +- `alice` = Eigentümer +- `developers` = Gruppe + +## chmod - Zugriffsrechte ändern + +### Symbolische Notation + +```bash +chmod [ugoa][+-=][rwx] datei +``` + +**Rechte hinzufügen:** +```bash +chmod u+x script.sh # Eigentümer: ausführbar +chmod g+w datei.txt # Gruppe: schreibbar +chmod o+r datei.txt # Andere: lesbar +chmod a+x script.sh # Alle: ausführbar +``` + +**Rechte entfernen:** +```bash +chmod u-x script.sh # Eigentümer: nicht ausführbar +chmod g-w datei.txt # Gruppe: nicht schreibbar +chmod o-r datei.txt # Andere: nicht lesbar +``` + +**Rechte setzen (überschreiben):** +```bash +chmod u=rw,g=r,o= datei.txt # User: rw, Group: r, Others: keine +chmod a=r datei.txt # Alle: nur lesen +``` + +### Numerische Notation (Oktal) + +Rechte als dreistellige Oktalzahl: + +| Wert | Rechte | Bedeutung | +|------|--------|-----------| +| 0 | `---` | Keine Rechte | +| 1 | `--x` | Ausführen | +| 2 | `-w-` | Schreiben | +| 3 | `-wx` | Schreiben + Ausführen | +| 4 | `r--` | Lesen | +| 5 | `r-x` | Lesen + Ausführen | +| 6 | `rw-` | Lesen + Schreiben | +| 7 | `rwx` | Alle Rechte | + +**Häufige Kombinationen:** +```bash +chmod 644 datei.txt # rw-r--r-- (Standard für Dateien) +chmod 755 script.sh # rwxr-xr-x (Standard für Scripts) +chmod 700 privat.key # rwx------ (Nur Eigentümer) +chmod 600 ~/.ssh/id_rsa # rw------- (SSH-Schlüssel) +chmod 777 verzeichnis # rwxrwxrwx (Alle Rechte - UNSICHER!) +``` + +Beispiel: `chmod 755` bedeutet: +- User: 7 (rwx) +- Group: 5 (r-x) +- Others: 5 (r-x) + +### Rekursiv + +```bash +chmod -R 755 /pfad/zum/verzeichnis +``` + +**Nur Verzeichnisse oder nur Dateien:** +```bash +find . -type d -exec chmod 755 {} + # Alle Verzeichnisse +find . -type f -exec chmod 644 {} + # Alle Dateien +``` + +### Spezielle Rechte + +**Sticky Bit** (nur Eigentümer kann löschen): +```bash +chmod +t /tmp # Symbolic +chmod 1777 verzeichnis # Numeric (rwxrwxrwt) +``` + +**SUID** (läuft mit Rechten des Eigentümers): +```bash +chmod u+s /usr/bin/passwd # Symbolic +chmod 4755 datei # Numeric (rwsr-xr-x) +``` + +**SGID** (neue Dateien erben Gruppe): +```bash +chmod g+s verzeichnis # Symbolic +chmod 2755 verzeichnis # Numeric (rwxr-sr-x) +``` + +### Praktische Beispiele + +**Script ausführbar machen:** +```bash +chmod +x meinscript.sh +./meinscript.sh +``` + +**SSH-Verzeichnis absichern:** +```bash +chmod 700 ~/.ssh +chmod 600 ~/.ssh/id_rsa +chmod 644 ~/.ssh/id_rsa.pub +chmod 600 ~/.ssh/authorized_keys +``` + +**Web-Verzeichnis:** +```bash +chmod -R 755 /var/www/html +find /var/www/html -type f -exec chmod 644 {} + +find /var/www/html -type d -exec chmod 755 {} + +``` + +**Projekt-Verzeichnis:** +```bash +chmod -R u+rwX,g+rX,o-rwx projektordner +``` + +(`X` = ausführbar nur für Verzeichnisse) + +## chown - Eigentümer und Gruppe ändern + +### Grundsyntax + +```bash +chown [OPTIONEN] EIGENTÜMER[:GRUPPE] DATEI +``` + +### Eigentümer ändern + +```bash +chown alice datei.txt +``` + +### Eigentümer und Gruppe ändern + +```bash +chown alice:developers datei.txt +``` + +### Nur Gruppe ändern + +```bash +chown :developers datei.txt +``` + +Oder mit `chgrp`: +```bash +chgrp developers datei.txt +``` + +### Rekursiv + +```bash +chown -R alice:developers /pfad/zum/verzeichnis +``` + +### Von anderem Benutzer übernehmen + +```bash +chown --reference=referenzdatei zieldatei +``` + +### Praktische Beispiele + +**Web-Server Verzeichnis:** +```bash +sudo chown -R www-data:www-data /var/www/html +``` + +**Home-Verzeichnis korrigieren:** +```bash +sudo chown -R alice:alice /home/alice +``` + +**Nach Copy von Root:** +```bash +sudo cp /root/datei.txt /home/alice/ +sudo chown alice:alice /home/alice/datei.txt +``` + +**Nur Dateien, nicht Verzeichnisse:** +```bash +find /pfad -type f -exec chown alice:developers {} + +``` + +**Nur bei Bedarf ändern:** +```bash +find /pfad ! -user alice -exec chown alice {} + +find /pfad ! -group developers -exec chgrp developers {} + +``` + +### Symbolische Links + +Standardmäßig ändert `chown` das Ziel des Links: + +```bash +chown alice symlink # ändert Ziel +chown -h alice symlink # ändert nur den Link selbst +``` + +## Kombinierte Anwendung + +### Berechtigungen komplett setzen + +```bash +sudo chown -R www-data:www-data /var/www/html +sudo find /var/www/html -type d -exec chmod 755 {} + +sudo find /var/www/html -type f -exec chmod 644 {} + +``` + +### Projekt-Setup + +```bash +sudo chown -R alice:developers /opt/projekt +chmod -R u+rwX,g+rwX,o-rwx /opt/projekt +``` + +### Backup wiederherstellen + +```bash +sudo tar -xpf backup.tar.gz # -p bewahrt Rechte +sudo chown -R alice:alice /home/alice/restored/ +``` + +## Berechtigungen prüfen + +```bash +ls -l datei.txt # Einfache Ansicht +stat datei.txt # Detaillierte Info +getfacl datei.txt # ACLs anzeigen (falls gesetzt) +``` + +## Eigentümer-ID statt Name + +```bash +chown 1000:1000 datei.txt # Verwendet UID und GID direkt +``` + +UIDs anzeigen: +```bash +id alice # UID und GIDs von alice +``` + +## Fehler vermeiden + +### Rekursive Änderungen testen + +```bash +# Erst anzeigen +find /pfad -ls + +# Dann ändern +sudo chown -R alice:developers /pfad +``` + +### NIEMALS auf Root-Verzeichnis + +```bash +# GEFÄHRLICH - bricht System +sudo chown -R user:user / # NIEMALS! +sudo chmod -R 777 / # NIEMALS! + +# Nur eigene Verzeichnisse +sudo chown -R user:user /home/user +``` + +### Zu permissive Rechte + +```bash +# FALSCH - macht alles ausführbar +chmod -R 777 verzeichnis # NICHT verwenden! + +# RICHTIG - differenziert +find verzeichnis -type d -exec chmod 755 {} + +find verzeichnis -type f -exec chmod 644 {} + +``` + +### Systemdateien + +```bash +# Wichtige Systemdateien sollten root gehören +ls -l /etc/passwd /etc/shadow +# -rw-r--r-- 1 root root ... /etc/passwd +# -rw-r----- 1 root shadow ... /etc/shadow +``` + +## Mit sudo + +`chown` erfordert meist Root-Rechte: + +```bash +sudo chown root:root /etc/wichtig.conf +sudo chmod 644 /etc/wichtig.conf +``` + +Ohne sudo: +```bash +# Nur eigene Dateien +chmod 644 meine_datei.txt + +# chown nur als root +chown alice datei.txt # Permission denied (außer eigene Datei) +``` + +## Zusammenfassung + +| Befehl | Zweck | Beispiel | +|--------|-------|----------| +| `chmod` | Rechte ändern | `chmod 755 script.sh` | +| `chown` | Eigentümer ändern | `chown alice:developers file` | +| `chgrp` | Nur Gruppe ändern | `chgrp developers file` | +| `ls -l` | Rechte anzeigen | `ls -l file` | +| `stat` | Details anzeigen | `stat file` | + +**Standard-Rechte:** +- Dateien: `644` (rw-r--r--) +- Scripts: `755` (rwxr-xr-x) +- Verzeichnisse: `755` (rwxr-xr-x) +- Private Dateien: `600` (rw-------) + +## Siehe auch + +- [[find]] - Dateien mit bestimmten Rechten/Eigentümern finden +- [[ls]] - Rechte und Eigentümer anzeigen +- [[Symlinks]] - Links bleiben bei chown erhalten +- [[tar]] - Rechte in Archiven bewahren +- [[rsync]] - Rechte bei Synchronisation diff --git a/Computerkram/Linux/BASH Basics/PATH und Alias.md b/Computerkram/Linux/BASH Basics/PATH und Alias.md new file mode 100644 index 0000000..c16826d --- /dev/null +++ b/Computerkram/Linux/BASH Basics/PATH und Alias.md @@ -0,0 +1,115 @@ +# Linux BASH: Permanente Verfügbarkeit von Dateien und Pfaden + +Es gibt mehrere Methoden, um Dateien oder Pfade in Linux BASH permanent verfügbar zu machen: + +## PATH-Variable erweitern + +### Temporär (aktuelle Session) +```bash +export PATH="$PATH:/pfad/zum/verzeichnis" +``` + +### Permanent für aktuellen Benutzer +Füge folgende Zeile in `~/.bashrc` oder `~/.profile` ein: +```bash +export PATH="$PATH:/pfad/zum/verzeichnis" +``` + +### Permanent systemweit +Bearbeite `/etc/environment`: +```bash +sudo nano /etc/environment +``` +Erweitere die PATH-Zeile: +``` +PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/dein/pfad" +``` + +## Symbolische Links erstellen + +### Link in systemweitem Bin-Verzeichnis +```bash +sudo ln -s /vollständiger/pfad/zur/datei /usr/local/bin/dateiname +``` + +### Link in persönlichem Bin-Verzeichnis +```bash +mkdir -p ~/bin +ln -s /vollständiger/pfad/zur/datei ~/bin/dateiname +# ~/bin zu PATH hinzufügen falls nicht vorhanden +echo 'export PATH="$PATH:$HOME/bin"' >> ~/.bashrc +``` + +## Aliase verwenden + +### In ~/.bashrc hinzufügen +```bash +alias meinprogramm='/vollständiger/pfad/zur/datei' +alias cdprojekt='cd /pfad/zum/projekt' +``` + +## Umgebungsvariablen für Pfade + +### In ~/.bashrc definieren +```bash +export MEIN_PROJEKT_PFAD="/pfad/zum/projekt" +export MEIN_SCRIPT_PFAD="/pfad/zu/scripts" +``` + +Verwendung: +```bash +cd $MEIN_PROJEKT_PFAD +$MEIN_SCRIPT_PFAD/meinscript.sh +``` + +## Anwendung der Änderungen + +Nach Bearbeitung der Konfigurationsdateien: +```bash +source ~/.bashrc +# oder +exec bash +# oder Terminal neu starten +``` + +## Praxisbeispiele + +### Eigene Scripts verfügbar machen +```bash +# 1. Persönliches Scripts-Verzeichnis erstellen +mkdir -p ~/scripts + +# 2. Script dort ablegen +cp meinscript.sh ~/scripts/ + +# 3. Ausführbar machen +chmod +x ~/scripts/meinscript.sh + +# 4. PATH erweitern in ~/.bashrc +echo 'export PATH="$PATH:$HOME/scripts"' >> ~/.bashrc + +# 5. Änderungen laden +source ~/.bashrc +``` + +### Häufig verwendete Verzeichnisse +```bash +# In ~/.bashrc +alias proj='cd /home/user/projekte' +alias docs='cd /home/user/dokumente' +export WORKSPACE="/home/user/workspace" +``` + +## Wichtige Hinweise + +- **Reihenfolge im PATH**: Erste Treffer werden verwendet +- **Sicherheit**: Keine unsicheren Verzeichnisse in PATH aufnehmen +- **Systemweite vs. Benutzer-spezifische** Änderungen beachten +- **Backup**: Konfigurationsdateien vor Änderungen sichern + +--- + +**Verwandte Themen:** +- [[Linux Shell Konfiguration]] +- [[BASH Umgebungsvariablen]] +- [[Linux Dateisystem Navigation]] \ No newline at end of file diff --git a/Computerkram/Linux/BASH Basics/Symlinks.md b/Computerkram/Linux/BASH Basics/Symlinks.md new file mode 100644 index 0000000..823a15e --- /dev/null +++ b/Computerkram/Linux/BASH Basics/Symlinks.md @@ -0,0 +1,107 @@ +# Symbolische Links (Symlinks) + +Ein symbolischer Link (Symlink) ist eine spezielle Datei, die auf eine andere Datei oder ein Verzeichnis verweist. + +## Symlink erstellen + +```bash +ln -s /pfad/zum/ziel /pfad/zum/link +``` + +Optionen: +- `-s` → Symlink erstellen (statt Hardlink) +- `-f` → vorhandenen Link überschreiben +- `-n` → falls Link auf Verzeichnis verweist, Link selbst überschreiben + +Beispiel: + +```bash +ln -s /opt/programm/binary /usr/local/bin/programm +``` + +## Ziel eines Symlinks anzeigen + +```bash +readlink meinlink +``` + +Mit absolutem Pfad (löst verschachtelte Links auf): + +```bash +readlink -f meinlink +``` + +Beispiel: + +```bash +$ readlink mysoftlink +../zielordner/datei.txt + +$ readlink -f mysoftlink +/home/user/zielordner/datei.txt +``` + +## Symlink aktualisieren + +Einen Symlink kann man nicht direkt ändern, sondern muss ihn neu erstellen: + +```bash +ln -sfn /neues/ziel meinlink +``` + +Beispiel: + +```bash +#!/bin/bash +link="meinlink" + +# Aktuelles Ziel auslesen +altes_ziel=$(readlink "$link") +echo "Aktuelles Ziel: $altes_ziel" + +# Neues Ziel setzen +neues_ziel="/pfad/zum/neuen/ziel" +ln -sfn "$neues_ziel" "$link" + +echo "Neues Ziel: $(readlink $link)" +``` + +## Symlinks vs. Hardlinks + +**Symlinks:** +- Verweisen auf Pfad (nicht auf Inode) +- Können auf Dateien und Verzeichnisse verweisen +- Funktionieren über Dateisystemgrenzen hinweg +- Brechen, wenn Ziel gelöscht wird + +**Hardlinks:** +- Verweisen direkt auf Inode +- Nur für Dateien (nicht für Verzeichnisse) +- Müssen im gleichen Dateisystem liegen +- Bleiben gültig, auch wenn Originaldatei gelöscht wird + +## Desktop-Verknüpfungen erstellen + +Für Desktop-Umgebungen (GNOME, KDE, XFCE) verwendet man `.desktop`-Dateien: + +**weblink.desktop:** +```ini +[Desktop Entry] +Name=Open ChatGPT +Type=Link +URL=https://chat.openai.com/ +Icon=web-browser +``` + +Ausführbar machen: + +```bash +chmod +x weblink.desktop +``` + +## Siehe auch + +- [[find]] - Dateien suchen (z.B. nach Symlinks mit `-type l`) +- [[ls]] - Symlinks in Verzeichnissen anzeigen +- [[Dateiberechtigungen]] - Rechte von Links und Zielen +- [[lsblk]] - Block-Geräte anzeigen diff --git a/Computerkram/Linux/BASH Basics/awk.md b/Computerkram/Linux/BASH Basics/awk.md new file mode 100644 index 0000000..7b252f0 --- /dev/null +++ b/Computerkram/Linux/BASH Basics/awk.md @@ -0,0 +1,257 @@ +# awk - Textverarbeitung und Datenextraktion + +`awk` ist eine mächtige Programmiersprache für Textverarbeitung, besonders nützlich für spaltenbasierte Daten. + +## Grundsyntax + +```bash +awk 'MUSTER { AKTION }' datei.txt +``` + +## Spalten ausgeben + +### Einzelne Spalten + +```bash +awk '{print $1}' datei.txt # Erste Spalte +awk '{print $2}' datei.txt # Zweite Spalte +awk '{print $NF}' datei.txt # Letzte Spalte +``` + +`$0` = ganze Zeile, `$1` = erste Spalte, `$2` = zweite, etc. + +### Mehrere Spalten + +```bash +awk '{print $1, $3}' datei.txt +awk '{print $1 " - " $3}' datei.txt +``` + +## Trennzeichen (Delimiter) + +### Standard (Leerzeichen/Tab) + +```bash +awk '{print $1}' datei.txt +``` + +### Eigenes Trennzeichen + +```bash +awk -F: '{print $1}' /etc/passwd # Doppelpunkt +awk -F, '{print $1, $3}' datei.csv # Komma +awk -F'|' '{print $2}' datei.txt # Pipe +``` + +### Mehrere Trennzeichen + +```bash +awk -F'[,:]' '{print $1}' datei.txt +``` + +## Muster (Pattern) + +### Zeilen mit bestimmtem Text + +```bash +awk '/ERROR/ {print}' logfile.txt +awk '/ERROR/' logfile.txt # Kurzform +``` + +### Reguläre Ausdrücke + +```bash +awk '/^[0-9]/ {print}' datei.txt # Zeilen mit Zahl am Anfang +awk '/ERROR|WARNING/' logfile.txt # ERROR oder WARNING +``` + +### Spaltenbasierte Bedingungen + +```bash +awk '$3 > 100 {print}' datei.txt # 3. Spalte > 100 +awk '$1 == "root" {print}' /etc/passwd # 1. Spalte = "root" +awk '$2 != "active" {print}' status.txt # 2. Spalte ≠ "active" +``` + +### Mehrere Bedingungen + +```bash +awk '$3 > 100 && $4 < 200 {print}' datei.txt +awk '$1 == "Alice" || $1 == "Bob" {print}' datei.txt +``` + +## Berechnungen + +### Summe + +```bash +awk '{sum += $1} END {print sum}' zahlen.txt +``` + +### Durchschnitt + +```bash +awk '{sum += $1; count++} END {print sum/count}' zahlen.txt +``` + +### Maximum/Minimum + +```bash +awk 'BEGIN {max=0} {if($1>max) max=$1} END {print max}' zahlen.txt +awk 'NR==1 {min=$1} {if($1=10 && NR<=20' datei.txt # Zeilen 10-20 +``` + +Wichtige Variablen: +- `NR` = Nummer der aktuellen Zeile +- `NF` = Anzahl der Felder +- `FS` = Field Separator (Eingabe) +- `OFS` = Output Field Separator (Ausgabe) + +## BEGIN und END + +```bash +awk 'BEGIN {print "Start"} {print} END {print "Ende"}' datei.txt +``` + +```bash +awk 'BEGIN {FS=":"; OFS="\t"} {print $1, $3}' /etc/passwd +``` + +## Praktische Beispiele + +### /etc/passwd auswerten + +```bash +# Alle Benutzernamen +awk -F: '{print $1}' /etc/passwd + +# User mit UID >= 1000 +awk -F: '$3 >= 1000 {print $1}' /etc/passwd + +# User und Shell +awk -F: '{print $1 ": " $7}' /etc/passwd +``` + +### Prozesse analysieren + +```bash +# Speichernutzung +ps aux | awk '{sum += $6} END {print sum/1024 " MB"}' + +# Top 5 Prozesse nach Speicher +ps aux | awk '{print $6, $11}' | sort -rn | head -5 +``` + +### CSV-Dateien + +```bash +# Zweite Spalte summieren +awk -F, '{sum += $2} END {print sum}' data.csv + +# Filtern und ausgeben +awk -F, '$3 > 1000 {print $1, $2}' sales.csv +``` + +### Logfile-Analyse + +```bash +# Nur ERROR-Zeilen mit Zeitstempel +awk '/ERROR/ {print $1, $2, $0}' app.log + +# Fehler zählen +awk '/ERROR/ {count++} END {print count}' app.log + +# Nach Zeit filtern +awk '$1 >= "2025-11-07" && $1 <= "2025-11-08"' log.txt +``` + +### Apache/Nginx Logs + +```bash +# IP-Adressen extrahieren +awk '{print $1}' access.log | sort | uniq -c | sort -rn + +# Nur 404-Fehler +awk '$9 == 404 {print $7}' access.log +``` + +### Duplikate zählen + +```bash +awk '{count[$1]++} END {for(key in count) print key, count[key]}' datei.txt +``` + +## Arrays + +```bash +awk '{arr[$1] += $2} END {for (key in arr) print key, arr[key]}' datei.txt +``` + +## Mehrere Dateien + +```bash +awk '{print FILENAME, $0}' datei1.txt datei2.txt +``` + +## Mit Pipes + +```bash +cat datei.txt | awk '{print $1}' +ls -l | awk '{print $9, $5}' +df -h | awk 'NR>1 {print $1, $5}' +``` + +## Komplexes Beispiel + +```bash +# Benutzerdefinierte Funktion +awk ' + function celsius(f) { + return (f - 32) * 5/9 + } + { + printf "%s: %.2f°C\n", $1, celsius($2) + } +' temperatures.txt +``` + +## Vergleich: awk vs. andere Tools + +| Task | Tool | +|------|------| +| Spalten extrahieren | `awk '{print $2}'` oder `cut -f2` | +| Suchen | `awk '/pattern/'` oder `grep pattern` | +| Ersetzen | `sed 's/alt/neu/'` | +| Rechnen | `awk '{sum+=$1}'` | + +## Siehe auch + +- [[grep]] - Textsuche +- [[sed]] - Stream-Editor +- [[find]] - Dateien finden +- [[BASH Funktionen]] - awk in Funktionen nutzen +- [[ls]] - Ausgabe mit awk verarbeiten diff --git a/Computerkram/Linux/BASH Basics/find.md b/Computerkram/Linux/BASH Basics/find.md new file mode 100644 index 0000000..be660c9 --- /dev/null +++ b/Computerkram/Linux/BASH Basics/find.md @@ -0,0 +1,362 @@ +# find - Dateien und Verzeichnisse suchen + +Der Befehl `find` durchsucht Verzeichnisse rekursiv nach Dateien oder Ordnern anhand verschiedener Kriterien. + +## Grundsyntax + +```bash +find [Pfad] [Suchkriterien] [Aktionen] +``` + +## Suchkriterien + +### Nach Namen suchen + +```bash +find . -name "datei.txt" # exakte Übereinstimmung +find . -iname "datei.txt" # case-insensitive +find . -name "*.log" # mit Wildcards +``` + +### Nach Dateityp suchen + +```bash +find . -type f # nur Dateien +find . -type d # nur Verzeichnisse +find . -type l # symbolische Links +``` + +### Nach Dateigröße suchen + +```bash +find . -size +10M # größer als 10 MB +find . -size -100k # kleiner als 100 KB +find . -size 0 # leere Dateien +``` + +### Nach Berechtigungen suchen + +```bash +find . -perm 644 # Dateien mit Rechten 644 +find . -user alice # Dateien von User "alice" +find . -group admins # Dateien von Gruppe "admins" +``` + +### Suchtiefe begrenzen + +```bash +find . -maxdepth 1 -type f +``` + +Nur im aktuellen Ordner, nicht in Unterordnern. + +## Suche nach Datum und Zeit + +### Zeitstempel-Typen + +- **mtime** (modification time) = Inhalt geändert +- **atime** (access time) = Datei gelesen +- **ctime** (change time) = Metadaten geändert (chmod, chown) + +### Relative Zeitangaben (Tage) + +```bash +find . -mtime -7 # in den letzten 7 Tagen geändert +find . -mtime +30 # älter als 30 Tage +find . -atime -1 # in den letzten 24 Stunden geöffnet +find . -ctime -1 # Metadaten in letzten 24h geändert +``` + +Dateien zwischen X und Y Tagen: + +```bash +find . -mtime +7 -mtime -30 +``` + +### Absolute Zeitangaben (Datum, GNU find) + +```bash +find . -newermt "2025-04-01" # mtime nach Datum +find . -newerat "2025-04-01" # atime nach Datum +find . -newerct "2025-04-01" # ctime nach Datum +find . -newermt "2023-09-01" ! -newermt "2023-09-10" # zwischen zwei Daten +``` + +**Hinweis:** `-newermt/at/ct` sind GNU-Erweiterungen (nicht auf BSD/macOS). + +### Mit Referenzdatei + +```bash +touch -d "2025-04-01" /tmp/refdate +find . -newer /tmp/refdate +``` + +### Übersicht Zeitoptionen + +| Option | Bedeutung | +|--------|-----------| +| `-mtime -7` | in den letzten 7 Tagen geändert | +| `-mtime +30` | älter als 30 Tage | +| `-atime -2` | in den letzten 2 Tagen geöffnet | +| `-ctime -1` | Metadaten in letzten 24h geändert | +| `-newermt "2023-09-01"` | mtime nach Datum (GNU) | +| `-newerat "2023-09-01"` | atime nach Datum (GNU) | +| `-newerct "2023-09-01"` | ctime nach Datum (GNU) | +| `-newer datei.txt` | neuer als Referenzdatei | + +## Bedingungen kombinieren + +### UND-Verknüpfung (Standard) + +```bash +find . -type f -size +1M -mtime -7 +``` + +Dateien größer als 1 MB UND in den letzten 7 Tagen geändert. + +### ODER-Verknüpfung + +```bash +find . -type f \( -name "*.jpg" -o -name "*.png" \) +``` + +Alle `.jpg` ODER `.png` Dateien. + +### Negation + +```bash +find . -type f ! -iname "*.mp3" +``` + +Alle Dateien, die NICHT auf `.mp3` enden. + +Mehrere Endungen ausschließen: + +```bash +find . -type f ! \( -iname "*.mp3" -o -iname "*.flac" \) +``` + +## Aktionen auf gefundene Dateien + +### Anzeigen + +```bash +find . -name "*.log" -print # Standard +find . -name "*.log" -ls # mit Details +``` + +### Dateien löschen + +**Grundprinzip:** Immer erst testen, dann löschen! + +```bash +# 1. Testen +find . -name "*.tmp" -print + +# 2. Anzahl prüfen +find . -name "*.tmp" | wc -l + +# 3. Dry-run +find . -name "*.tmp" -exec echo rm {} + + +# 4. Löschen +find . -name "*.tmp" -delete +``` + +Alternative mit `-exec`: + +```bash +find . -name "*.tmp" -exec rm {} + # effizient (mehrere auf einmal) +find . -name "*.tmp" -exec rm {} \; # einzeln +find . -name "*.tmp" -exec rm -i {} \; # mit Rückfrage +``` + +Mit xargs (sicher bei Leerzeichen): + +```bash +find . -name "*.tmp" -print0 | xargs -0 rm +``` + +### Mit -exec Befehle ausführen + +```bash +find . -name "*.log" -exec rm {} + # Löschen +find . -type f -name "*.sh" -exec chmod +x {} + # Ausführbar machen +find /etc -type f -mtime -1 -exec cp {} /backup/ \; # Kopieren +find . -type f -name "*.log" -mtime +7 -exec gzip {} + # Komprimieren +``` + +- `{}` = Platzhalter für gefundene Datei +- `\;` = Ende des Befehls (einzeln, langsamer) +- `+` = mehrere Dateien gleichzeitig (effizienter) + +### Komplexe Shell-Befehle + +```bash +find . -type f -name "*.jpg" -exec sh -c 'for f; do + convert "$f" -resize 800x "${f%.jpg}_small.jpg" +done' _ {} + +``` + +## Pfad- und Namensfilter + +### Mit -path (Glob-Muster) + +```bash +find ~/Musik -type f -path "*/zzz Verschiedene/AlbumArt_*" +``` + +`-path` verwendet Shell-Wildcards (Globs), nicht reguläre Ausdrücke. + +### Mit -regex (Reguläre Ausdrücke) + +```bash +find ~/Musik -type f -regextype posix-extended \ + -regex '.*/zzz Verschiedene/AlbumArt_.*' +``` + +`-regex` matcht den gesamten Pfad, daher oft `.*` am Anfang nötig. + +## Praktische Anwendungsfälle + +### Alte Dateien löschen + +```bash +find /tmp -type f -mtime +7 -delete +``` + +### Leere Dateien/Verzeichnisse finden + +```bash +find . -type f -empty # leere Dateien +find . -type d -empty # leere Ordner +``` + +### Dateien mit falschen Rechten + +```bash +find / -type f -perm -o+w # weltweit schreibbar +``` + +### Große Dateien finden + +```bash +find /home -type f -size +100M +find . -type f -exec du -h {} + | sort -rh | head -10 # Top 10 größte +``` + +### Dateien nach Datum und Pfad + +```bash +find ~/Musik -type f \ + -newermt "2025-04-01" \ + -path "*/zzz Verschiedene/AlbumArt_*" \ + -print +``` + +### Dateien sichern + +```bash +find /etc -type f -mtime -1 -exec cp {} /backup/ \; +``` + +### Backup-Kandidaten mit Datum + +```bash +find /backups -type f -name "*.tar.gz" \ + -newermt "2023-08-01" ! -newermt "2023-08-31" +``` + +### Logfile-Analyse + +```bash +find /var/log -type f -size +100M -newermt "2023-09-01" +``` + +### Nur Dateien, nicht Verzeichnisse ändern + +```bash +find . -type f -exec chmod 644 {} + +find . -type d -exec chmod 755 {} + +``` + +## Best Practices und Fehler vermeiden + +### Sicherheit beim Löschen + +```bash +# IMMER erst testen +find . -name "*.tmp" -print +find . -name "*.tmp" | wc -l +find . -name "*.tmp" -exec echo rm {} + + +# Dann löschen +find . -name "*.tmp" -delete +``` + +### Leerzeichen in Dateinamen + +```bash +# RICHTIG: -print0 und xargs -0 +find . -name "*.txt" -print0 | xargs -0 rm + +# RICHTIG: -exec mit + +find . -name "*.txt" -exec rm {} + + +# FALSCH: Pipe ohne -print0 +find . -name "*.txt" | rm # funktioniert nicht! +``` + +### Trailing Slash bei -path + +```bash +find . -path "*/ordner/*" # Dateien IN ordner/ +find . -path "*/ordner" # NUR ordner/ selbst +``` + +### -delete Reihenfolge + +```bash +# RICHTIG: -type f VOR -delete +find . -type f -name "*.tmp" -delete + +# FALSCH: kann Verzeichnisse löschen +find . -name "*.tmp" -delete +``` + +### Zu viele Argumente + +```bash +# FALSCH: kann "Argument list too long" geben +find . -name "*.txt" -exec rm {} \; + +# RICHTIG: mit + +find . -name "*.txt" -exec rm {} + + +# RICHTIG: mit xargs +find . -name "*.txt" -print0 | xargs -0 rm +``` + +## Alternative Tools + +- **fd** - moderner, schneller find-Ersatz mit besserer Syntax +- **ripgrep (rg)** - für Textsuche in Dateien +- **locate** - schnelle Dateinamensuche (nutzt Datenbank) + +Beispiel mit fd: + +```bash +fd "*.log" # Einfacher als find +fd -t f -s +100M # Dateien > 100MB +fd -e jpg -x convert {} ... # Mit exec +``` + +## Siehe auch + +- [[ls]] - Dateien auflisten +- [[grep]] - Textsuche in gefundenen Dateien +- [[Dateiberechtigungen]] - Rechte und Eigentümer von Dateien +- [[tar]] - Gefundene Dateien archivieren +- [[rsync]] - Dateien synchronisieren +- [[sed]] - Gefundene Dateien bearbeiten +- [[awk]] - Ausgabe von find verarbeiten diff --git a/Computerkram/Linux/BASH Basics/fstab Credentials.md b/Computerkram/Linux/BASH Basics/fstab Credentials.md new file mode 100644 index 0000000..2cad51f --- /dev/null +++ b/Computerkram/Linux/BASH Basics/fstab Credentials.md @@ -0,0 +1,127 @@ +# fstab - Credentials sicher speichern + +Zugangsdaten (Benutzername/Passwort) sollten nicht im Klartext in `/etc/fstab` stehen. + +## Credentials-Datei verwenden + +Viele Treiber wie `cifs` oder `smbfs` unterstützen separate Credential-Dateien. + +### fstab-Eintrag + +```fstab +//server/share /mnt/share cifs credentials=/etc/samba/credentials,iocharset=utf8,uid=1000,gid=1000 0 0 +``` + +### Credentials-Datei erstellen + +**/etc/samba/credentials:** +``` +username=meinuser +password=meinpasswort +domain=meinedomain +``` + +### Datei absichern + +```bash +sudo chmod 600 /etc/samba/credentials +sudo chown root:root /etc/samba/credentials +``` + +Nur root kann die Datei lesen, `/etc/fstab` enthält keine Secrets. + +## Kernel Keyring nutzen + +Für temporäre Mounts (z.B. bei CIFS): + +```bash +cifscreds add -u meinuser servername +``` + +Dann kann der Mount in fstab ohne Passwort erfolgen - der Kernel holt die Daten aus dem Keyring. + +**Hinweis:** Funktioniert hauptsächlich für interaktive Sessions, nicht für automatische Boot-Mounts. + +## Systemd-Units verwenden + +Statt `/etc/fstab` kann man systemd `.mount`-Units mit Credentials nutzen. + +**Beispiel:** `/etc/systemd/system/mnt-share.mount` + +```ini +[Unit] +Description=SMB Share Mount + +[Mount] +What=//server/share +Where=/mnt/share +Type=cifs +Options=credentials=/etc/samba/credentials,iocharset=utf8,uid=1000,gid=1000 + +[Install] +WantedBy=multi-user.target +``` + +Aktivieren: + +```bash +sudo systemctl daemon-reload +sudo systemctl enable mnt-share.mount +sudo systemctl start mnt-share.mount +``` + +## Kerberos-Authentifizierung + +Für Netzwerke mit Active Directory oder Kerberos: + +### NFS mit Kerberos + +```fstab +server:/export /mnt/nfs nfs sec=krb5,rw 0 0 +``` + +### CIFS mit Kerberos + +```fstab +//server/share /mnt/share cifs sec=krb5,multiuser,rw 0 0 +``` + +Keine Passwörter nötig - Authentifizierung über Kerberos-Tickets. + +## Secrets-Management-Systeme + +Für Produktivumgebungen mit höheren Sicherheitsanforderungen: + +- **HashiCorp Vault** - zentrales Secrets-Management +- **AWS Secrets Manager** - für Cloud-Umgebungen +- **GPG-verschlüsselte Dateien** - lokal verschlüsselt + +Beispiel mit GPG: + +```bash +# Credentials verschlüsselt speichern +echo "username=user\npassword=pass" | gpg -e -r you@example.com > /etc/samba/credentials.gpg + +# In Mount-Skript entschlüsseln +gpg -d /etc/samba/credentials.gpg > /tmp/credentials +mount -t cifs -o credentials=/tmp/credentials //server/share /mnt/share +rm /tmp/credentials +``` + +## Zusammenfassung + +| Methode | Sicherheit | Komplexität | Anwendungsfall | +|---------|-----------|-------------|----------------| +| Credentials-Datei | Gut | Niedrig | Standard für CIFS/SMB | +| Kernel Keyring | Mittel | Mittel | Interaktive Sessions | +| Kerberos | Sehr gut | Hoch | Enterprise/AD-Umgebungen | +| Systemd-Credentials | Sehr gut | Mittel | Moderne Systeme | +| Secrets Manager | Sehr gut | Hoch | Produktivumgebungen | + +**Empfehlung:** Für den Alltag ist eine separate Credentials-Datei mit restriktiven Rechten (600) der beste Kompromiss aus Sicherheit und Einfachheit. + +## Siehe auch + +- [[Symlinks]] - Symbolische Links erstellen +- [[Dateiberechtigungen]] - Dateien absichern mit chmod/chown +- [[lsblk]] - Block-Geräte anzeigen diff --git a/Computerkram/Linux/BASH Basics/grep.md b/Computerkram/Linux/BASH Basics/grep.md new file mode 100644 index 0000000..3f9188d --- /dev/null +++ b/Computerkram/Linux/BASH Basics/grep.md @@ -0,0 +1,202 @@ +# grep - Textsuche in Dateien + +Der `grep`-Befehl durchsucht Dateien oder Textströme nach Mustern (Strings oder reguläre Ausdrücke). + +## Grundsyntax + +```bash +grep [OPTIONEN] MUSTER [DATEI...] +``` + +## Einfache Suche + +```bash +grep "suchtext" datei.txt +``` + +In mehreren Dateien: + +```bash +grep "suchtext" *.txt +``` + +Rekursiv in Verzeichnissen: + +```bash +grep -r "suchtext" /pfad/zum/verzeichnis +``` + +## Wichtige Optionen + +### Groß-/Kleinschreibung + +```bash +grep -i "suchtext" datei.txt # case-insensitive +``` + +### Zeilen mit Kontext + +```bash +grep -A 3 "suchtext" datei.txt # 3 Zeilen danach +grep -B 3 "suchtext" datei.txt # 3 Zeilen davor +grep -C 3 "suchtext" datei.txt # 3 Zeilen davor und danach +``` + +### Nur Dateinamen anzeigen + +```bash +grep -l "suchtext" *.txt # Dateien mit Treffer +grep -L "suchtext" *.txt # Dateien ohne Treffer +``` + +### Zeilennummern anzeigen + +```bash +grep -n "suchtext" datei.txt +``` + +### Anzahl der Treffer + +```bash +grep -c "suchtext" datei.txt +``` + +### Invertierte Suche (nicht enthalten) + +```bash +grep -v "suchtext" datei.txt +``` + +Zeigt alle Zeilen, die den Suchtext NICHT enthalten. + +### Ganzes Wort + +```bash +grep -w "wort" datei.txt +``` + +Findet "wort", aber nicht "worte" oder "hauptwort". + +## Reguläre Ausdrücke + +### Einfache Regex (Basic) + +```bash +grep "^Start" datei.txt # Zeilen, die mit "Start" beginnen +grep "Ende$" datei.txt # Zeilen, die mit "Ende" enden +grep "^$" datei.txt # Leere Zeilen +``` + +### Extended Regex + +```bash +grep -E "fehler|warnung" datei.txt # fehler ODER warnung +grep -E "[0-9]{3}-[0-9]{4}" datei.txt # Telefonnummern +grep -E "^(root|admin)" /etc/passwd # Zeilen mit root oder admin am Anfang +``` + +### Perl-kompatible Regex + +```bash +grep -P "\d{3}-\d{4}" datei.txt +``` + +## Praktische Anwendungsfälle + +### Logfiles durchsuchen + +```bash +grep -i "error" /var/log/syslog +grep -E "error|warning|critical" /var/log/syslog +``` + +### Mit Zeitstempel + +```bash +grep "2025-11-07" /var/log/application.log +``` + +### Konfigurationsdateien + +```bash +# Alle nicht-kommentierten Zeilen +grep -v "^#" /etc/ssh/sshd_config | grep -v "^$" +``` + +### In komprimierten Dateien + +```bash +zgrep "suchtext" datei.log.gz +``` + +### Mit find kombinieren + +```bash +find . -name "*.log" -exec grep -l "ERROR" {} + +``` + +### Mehrere Muster aus Datei + +```bash +grep -f muster.txt datei.txt +``` + +**muster.txt:** +``` +fehler +warnung +critical +``` + +## Pipe-Verwendung + +```bash +ps aux | grep firefox +cat datei.txt | grep -v "^#" | grep "wichtig" +dmesg | grep -i usb +``` + +## Farbige Ausgabe + +```bash +grep --color=auto "suchtext" datei.txt +``` + +Alias in `.bashrc` setzen: + +```bash +alias grep='grep --color=auto' +``` + +## Alternative Tools + +- **ripgrep (rg)** - sehr schnell, modern, empfohlen +- **ag (The Silver Searcher)** - schneller als grep +- **ack** - für Code-Suche optimiert + +Beispiel mit ripgrep: + +```bash +rg "suchtext" /pfad # automatisch rekursiv, ignoriert .gitignore +``` + +## Zusammenfassung wichtiger Optionen + +| Option | Beschreibung | +|--------|--------------| +| `-i` | Case-insensitive | +| `-r` | Rekursiv | +| `-n` | Mit Zeilennummern | +| `-c` | Anzahl der Treffer | +| `-l` | Nur Dateinamen | +| `-v` | Invertiert (nicht enthalten) | +| `-w` | Ganzes Wort | +| `-E` | Extended Regex | +| `-A/-B/-C` | Kontext anzeigen | + +## Siehe auch + +- [[find]] - Dateien nach Namen/Eigenschaften suchen +- [[sed]] - Stream-Editor für Textmanipulation +- [[awk]] - Textverarbeitung und Datenextraktion +- [[ls]] - Ausgabe von ls filtern diff --git a/Computerkram/Linux/BASH Basics/ls.md b/Computerkram/Linux/BASH Basics/ls.md new file mode 100644 index 0000000..865abe0 --- /dev/null +++ b/Computerkram/Linux/BASH Basics/ls.md @@ -0,0 +1,390 @@ +# ls - Dateien und Verzeichnisse auflisten + +Der `ls`-Befehl listet Dateien und Verzeichnisse auf und zeigt deren Eigenschaften. + +## Grundsyntax + +```bash +ls [OPTIONEN] [PFAD...] +``` + +## Grundlegende Verwendung + +### Einfache Auflistung + +```bash +ls # Aktuelles Verzeichnis +ls /pfad/zum/ordner # Bestimmtes Verzeichnis +ls datei.txt # Einzelne Datei +``` + +### Versteckte Dateien anzeigen + +```bash +ls -a # Alle Dateien (inkl. .dotfiles) +ls -A # Alle außer . und .. +``` + +## Detaillierte Ausgabe + +### Long Format (-l) + +```bash +ls -l +``` + +Beispielausgabe: +``` +-rw-r--r-- 1 alice developers 1234 Nov 7 10:00 datei.txt +drwxr-xr-x 2 alice developers 4096 Nov 7 09:30 ordner +lrwxrwxrwx 1 alice developers 15 Nov 7 08:00 link -> /pfad/zu/ziel +``` + +Spalten: +- **1. Zeichen**: Typ (`-` = Datei, `d` = Verzeichnis, `l` = Link) +- **2-10**: Rechte (rwx für User, Group, Others) +- **Zahl**: Anzahl Hardlinks +- **User**: Eigentümer +- **Group**: Gruppe +- **Größe**: in Bytes +- **Datum/Zeit**: letzte Änderung +- **Name**: Dateiname + +### Menschenlesbare Größen (-h) + +```bash +ls -lh +``` + +Beispielausgabe: +``` +-rw-r--r-- 1 user staff 12K Nov 7 10:00 file.txt +-rw-r--r-- 1 user staff 1.2M Nov 7 09:30 big.dat +drwxr-xr-x 2 user staff 4.0K Nov 7 08:00 ordner +``` + +Größen werden in KB, MB, GB statt Bytes angezeigt. + +## Sortierung + +### Nach Name (Standard) + +```bash +ls # Alphabetisch +ls -r # Umgekehrt +``` + +### Nach Änderungsdatum + +```bash +ls -lt # Neueste zuerst +ls -ltr # Älteste zuerst +``` + +### Nach Größe + +```bash +ls -lS # Größte zuerst +ls -lSr # Kleinste zuerst +``` + +### Nach Erweiterung + +```bash +ls -lX # Gruppiert nach Dateityp +``` + +## Rekursive Auflistung + +```bash +ls -R # Alle Unterverzeichnisse +ls -R /pfad # Ab bestimmtem Pfad +``` + +## Nur bestimmte Dateien + +### Mit Wildcards + +```bash +ls *.txt # Alle .txt Dateien +ls *.{jpg,png} # Alle .jpg und .png +ls file[0-9]* # file0, file1, file2, ... +``` + +### Nur Verzeichnisse + +```bash +ls -d */ # Nur Verzeichnisse +ls -ld */ # Mit Details +``` + +### Nur Dateien (keine Verzeichnisse) + +```bash +ls -p | grep -v / +``` + +## Farben + +```bash +ls --color=auto # Farbige Ausgabe +ls --color=never # Ohne Farben +ls --color=always # Immer Farben (auch in Pipes) +``` + +Typische Farben: +- **Blau**: Verzeichnisse +- **Grün**: Ausführbare Dateien +- **Cyan**: Symbolische Links +- **Rot**: Archive +- **Gelb**: Devices + +## Spezielle Formate + +### Einzelne Spalte + +```bash +ls -1 # Eine Datei pro Zeile +``` + +### Komma-getrennt + +```bash +ls -m # Komma-getrennte Liste +``` + +### Mit Inode-Nummern + +```bash +ls -i # Zeigt Inode-Nummern +``` + +### Numerische UIDs/GIDs + +```bash +ls -n # User/Group als Zahlen statt Namen +``` + +## Dateigrößen analysieren + +### Größe einzelner Dateien + +```bash +ls -lh datei.txt +``` + +Ausgabe: +``` +-rw-r--r-- 1 user staff 12K Nov 7 10:00 datei.txt +``` + +### Größe mit stat + +Nur die Größe in Bytes: + +```bash +stat -c%s datei.txt +``` + +Mit Dateiname: + +```bash +stat -c "%s %n" * +``` + +### Größe von Verzeichnissen + +`ls` zeigt nur die Größe des Verzeichniseintrags (meist 4K), nicht den Inhalt! + +Für echte Verzeichnisgröße nutze `du`: + +```bash +du -sh ordner/ # Gesamtgröße +du -h --max-depth=1 # Größen aller Unterordner +``` + +Beispielausgabe: +``` +200M ./Bilder +1.3G ./Videos +50K ./Dokumente +1.5G . +``` + +Mit 1000er-Schritten statt 1024er: + +```bash +du -h --si --max-depth=1 +``` + +### Nach Größe sortiert + +```bash +du -sh * | sort -h # Alle Dateien/Ordner sortiert +ls -lhS # Nur Dateien, größte zuerst +``` + +### Größte Dateien finden + +Top 10 größte Dateien: + +```bash +du -ah . | sort -rh | head -n 10 +``` + +Mit [[find]]: + +```bash +find . -type f -exec du -h {} + | sort -rh | head -n 10 +``` + +### Speicherplatznutzung überwachen + +Gesamter Speicherplatz: + +```bash +df -h # Dateisysteme +df -h /home # Bestimmter Mountpoint +``` + +## Zeitstempel + +### Änderungszeit (Standard) + +```bash +ls -l # Zeigt mtime (modification time) +``` + +### Zugriffszeit + +```bash +ls -lu # Zeigt atime (access time) +``` + +### Statusänderungszeit + +```bash +ls -lc # Zeigt ctime (change time) +``` + +### Mit vollständigem Zeitstempel + +```bash +ls -l --time-style=full-iso +ls -l --time-style=long-iso +ls -l --time-style=iso +``` + +## Praktische Kombinationen + +### Übersichtliche Dateiliste + +```bash +ls -lhA # Details, lesbar, alle außer . und .. +ls -lhAtr # Dazu sortiert nach Datum, älteste zuerst +``` + +### Schnelle Dateisuche + +```bash +ls -la | grep datei # Suche in aktueller Liste +``` + +### Nur Größen von Verzeichnissen + +```bash +du -sh */ # Alle Unterverzeichnisse +``` + +### Dateien nach Änderung heute + +```bash +ls -lt | head # Neueste Dateien +``` + +### Ausführbare Dateien finden + +```bash +ls -l | grep '^-..x' +``` + +### Große Dateien finden + +```bash +ls -lhS | head -n 10 # Top 10 größte Dateien +``` + +### Versteckte Dateien zählen + +```bash +ls -A | wc -l +``` + +## Nützliche Aliases + +Setze in `~/.bashrc`: + +```bash +alias ll='ls -lhA' +alias la='ls -A' +alias l='ls -CF' +alias lt='ls -lhAtr' +alias lsize='ls -lhS' +``` + +## Zusammen mit anderen Befehlen + +### Mit find + +```bash +find . -name "*.log" -exec ls -lh {} \; +``` + +### Mit grep + +```bash +ls -la | grep "Nov 7" # Dateien von heute +ls -la | grep "^d" # Nur Verzeichnisse +``` + +### Mit awk + +```bash +ls -l | awk '{print $9, $5}' # Name und Größe +``` + +### Mit xargs + +```bash +ls *.txt | xargs rm # VORSICHT: Löscht alle .txt +``` + +## Fehler vermeiden + +### Dateien mit Leerzeichen + +```bash +# FALSCH +ls *.txt | xargs rm + +# RICHTIG +find . -name "*.txt" -print0 | xargs -0 rm +``` + +### Alias-Konflikte + +Viele Systeme haben `ls` als Alias mit `--color=auto` definiert. Um den echten Befehl zu nutzen: + +```bash +\ls # Umgeht Alias +command ls # Umgeht Alias +/bin/ls # Direkter Pfad +``` + +## Siehe auch + +- [[find]] - Erweiterte Dateisuche mit Kriterien +- [[grep]] - Ausgabe filtern +- [[Dateiberechtigungen]] - Bedeutung der Rechtespalten +- [[lsblk]] - Block-Geräte statt Dateien +- [[du]] - Detaillierte Größenanalyse diff --git a/Computerkram/Linux/BASH Basics/lsblk.md b/Computerkram/Linux/BASH Basics/lsblk.md new file mode 100644 index 0000000..6c6c33f --- /dev/null +++ b/Computerkram/Linux/BASH Basics/lsblk.md @@ -0,0 +1,177 @@ +# lsblk - Block-Geräte auflisten + +Der Befehl `lsblk` (list block devices) zeigt eine hierarchische Übersicht aller Blockgeräte: Festplatten, SSDs, USB-Sticks, Partitionen, LVMs, RAID-Geräte usw. + +## Grundsyntax + +```bash +lsblk [OPTIONEN] [GERÄTE...] +``` + +Ohne Parameter werden alle erkannten Blockgeräte in Baumstruktur angezeigt. + +## Typische Ausgabe + +```bash +lsblk +``` + +Beispiel: + +``` +NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS +sda 8:0 0 512G 0 disk +├─sda1 8:1 0 512M 0 part /boot/efi +├─sda2 8:2 0 64G 0 part / +└─sda3 8:3 0 447.5G 0 part /home +sdb 8:16 1 128G 0 disk +└─sdb1 8:17 1 128G 0 part /media/usb +``` + +Spalten: +- **NAME** = Gerätename (sda, sdb, ...) +- **SIZE** = Größe +- **TYPE** = Art (disk, part, rom, lvm ...) +- **MOUNTPOINTS** = Einbindungspunkt im Dateisystem + +## Wichtige Optionen + +### Bestimmte Spalten anzeigen + +```bash +lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT +``` + +Beispiel: + +``` +NAME FSTYPE SIZE MOUNTPOINT +sda 512G +├─sda1 vfat 512M /boot/efi +├─sda2 ext4 64G / +└─sda3 ext4 447.5G /home +``` + +### Dateisystemtypen anzeigen + +```bash +lsblk -f +``` + +Zeigt Dateisystemtyp, UUID und Label. + +### Nur Geräte ohne Partitionen + +```bash +lsblk -d +``` + +Zeigt nur die Hauptgeräte (`sda`, `sdb`), keine Partitionen. + +### Alle Geräte inklusive leere + +```bash +lsblk -a +``` + +Zeigt auch Geräte ohne Medium (z.B. leere CD-Laufwerke). + +### Mit UUIDs und Labels + +```bash +lsblk -o NAME,SIZE,UUID,LABEL,MOUNTPOINT +``` + +Wichtig für eindeutige Identifizierung in `/etc/fstab`. + +### Nur Namen ausgeben + +```bash +lsblk -n -o NAME +``` + +Beispiel: + +``` +sda +sda1 +sda2 +sda3 +sdb +sdb1 +``` + +Praktisch für Skripte. + +### Listen- oder JSON-Format + +```bash +lsblk -l # Listenformat +lsblk -J # JSON-Format +``` + +## Praktische Anwendungsfälle + +### Herausfinden, welche Geräte angeschlossen sind + +```bash +lsblk +``` + +### Prüfen, welche Partitionen wohin gemountet sind + +```bash +lsblk -o NAME,SIZE,MOUNTPOINT +``` + +### Dateisystemtypen ermitteln + +```bash +lsblk -f +``` + +### Neu eingesteckten USB-Stick identifizieren + +Vorher: +```bash +lsblk +``` + +Stick einstecken, dann: +```bash +lsblk +``` + +Das neue Gerät (z.B. `sdb1`) erscheint. + +### UUIDs für fstab ermitteln + +```bash +lsblk -o NAME,UUID,MOUNTPOINT +``` + +### Geräte mit bestimmtem Dateisystem finden + +```bash +lsblk -o NAME,FSTYPE,SIZE | grep ext4 +``` + +## Zusammenfassung wichtiger Optionen + +| Option | Beschreibung | +|--------|--------------| +| `lsblk` | Baumstruktur aller Blockgeräte | +| `lsblk -f` | Mit Dateisystemtypen | +| `lsblk -d` | Nur Hauptgeräte | +| `lsblk -a` | Alle inkl. leere Geräte | +| `lsblk -o SPALTEN` | Bestimmte Spalten | +| `lsblk -l` | Listenformat | +| `lsblk -J` | JSON-Format | + +## Siehe auch + +- [[ls]] - Dateien und Verzeichnisse auflisten +- [[find]] - Dateien suchen +- [[fstab Credentials]] - Geräte automatisch einbinden +- [[Symlinks]] - Verknüpfungen zu Geräten +- [[Dateiberechtigungen]] - Rechte von Geräten prüfen diff --git a/Computerkram/Linux/BASH Basics/rsync.md b/Computerkram/Linux/BASH Basics/rsync.md new file mode 100644 index 0000000..f049f3b --- /dev/null +++ b/Computerkram/Linux/BASH Basics/rsync.md @@ -0,0 +1,275 @@ +# rsync - Dateien synchronisieren + +Der `rsync`-Befehl synchronisiert Dateien und Verzeichnisse effizient zwischen verschiedenen Orten (lokal oder über Netzwerk). + +## Grundsyntax + +```bash +rsync [OPTIONEN] QUELLE ZIEL +``` + +## Grundlegende Optionen + +Die häufigste Kombination: + +```bash +rsync -av quelle/ ziel/ +``` + +- `-a` = archive (behält Rechte, Zeitstempel, Symlinks) +- `-v` = verbose (zeigt Details) + +## Lokale Synchronisation + +### Verzeichnis synchronisieren + +```bash +rsync -av /quelle/verzeichnis/ /ziel/verzeichnis/ +``` + +**Wichtig:** Trailing Slash `/` macht einen Unterschied! + +```bash +rsync -av quelle/ ziel/ # Inhalt von quelle/ nach ziel/ +rsync -av quelle ziel/ # quelle/ als Unterordner in ziel/quelle/ +``` + +## Über Netzwerk (SSH) + +### Zu Remote-Server + +```bash +rsync -av /lokaler/pfad/ user@server:/remote/pfad/ +``` + +### Von Remote-Server + +```bash +rsync -av user@server:/remote/pfad/ /lokaler/pfad/ +``` + +### Anderen SSH-Port + +```bash +rsync -av -e "ssh -p 2222" /lokal/ user@server:/remote/ +``` + +## Wichtige Optionen + +### Fortschritt anzeigen + +```bash +rsync -av --progress quelle/ ziel/ +``` + +### Dry-run (simulieren) + +```bash +rsync -avn quelle/ ziel/ +``` + +- `-n` = dry-run (nichts ändern, nur anzeigen) + +### Dateien löschen im Ziel + +```bash +rsync -av --delete quelle/ ziel/ +``` + +Löscht Dateien im Ziel, die in der Quelle nicht existieren. + +### Kompression (für Netzwerk) + +```bash +rsync -avz quelle/ user@server:/remote/ +``` + +- `-z` = compress (während Übertragung) + +### Teilweise übertragene Dateien behalten + +```bash +rsync -av --partial quelle/ ziel/ +``` + +Nützlich bei unterbrochenen Übertragungen. + +### Bandbreite begrenzen + +```bash +rsync -av --bwlimit=1000 quelle/ ziel/ +``` + +Begrenzt auf 1000 KB/s. + +## Dateien ausschließen + +### Einzelne Muster + +```bash +rsync -av --exclude='*.tmp' --exclude='.git' quelle/ ziel/ +``` + +### Aus Datei + +```bash +rsync -av --exclude-from=exclude.txt quelle/ ziel/ +``` + +**exclude.txt:** +``` +*.tmp +*.log +.git/ +node_modules/ +``` + +### Nur bestimmte Dateien + +```bash +rsync -av --include='*.pdf' --exclude='*' quelle/ ziel/ +``` + +## Praktische Beispiele + +### Backup erstellen + +```bash +rsync -av --delete /home/user/dokumente/ /backup/dokumente/ +``` + +### Backup mit Zeitstempel + +```bash +rsync -av /quelle/ /backup/backup-$(date +%Y%m%d)/ +``` + +### Nur geänderte Dateien kopieren + +```bash +rsync -av --update quelle/ ziel/ +``` + +Überschreibt nur, wenn Quelle neuer ist. + +### Große Dateien übertragen + +```bash +rsync -av --progress --partial-dir=.rsync-partial quelle/ ziel/ +``` + +### Backup auf NAS + +```bash +rsync -av --delete /home/user/ user@nas:/backup/user/ +``` + +### Website hochladen + +```bash +rsync -avz --delete website/ user@webserver:/var/www/html/ +``` + +### Mit Ausschlüssen + +```bash +rsync -av --delete \ + --exclude='node_modules' \ + --exclude='.git' \ + --exclude='*.log' \ + projekt/ /backup/projekt/ +``` + +## Inkrementelles Backup + +```bash +#!/bin/bash +CURRENT=/backup/current +TIMESTAMP=$(date +%Y%m%d-%H%M%S) + +rsync -av --delete --link-dest=$CURRENT /quelle/ /backup/$TIMESTAMP/ +rm -f $CURRENT +ln -s $TIMESTAMP $CURRENT +``` + +Erstellt platzsparende Backups durch Hardlinks. + +## Rechte und Eigentümer + +### Rechte bewahren + +```bash +rsync -av quelle/ ziel/ # Standard mit -a +``` + +### Als Root mit Original-Eigentümer + +```bash +sudo rsync -av quelle/ ziel/ +``` + +### Nur als aktueller User + +```bash +rsync -rlptv quelle/ ziel/ +``` + +Ohne `-o` und `-g` (Owner und Group). + +## Fehler vermeiden + +### Dry-run erst testen + +```bash +rsync -avn --delete quelle/ ziel/ +``` + +Prüfe die Ausgabe, bevor du wirklich synchronisierst! + +### Slash bei Quelle beachten + +```bash +rsync -av quelle/ ziel/ # Inhalt synchronisieren +rsync -av quelle ziel/ # Ordner synchronisieren +``` + +### Mit --delete vorsichtig sein + +```bash +# FALSCH - löscht alles im Ziel! +rsync -av --delete /leerer/ordner/ /wichtig/ + +# RICHTIG - erst prüfen +rsync -avn --delete quelle/ ziel/ +``` + +## Vergleich mit anderen Tools + +| Tool | Geschwindigkeit | Delta-Transfer | Netzwerk | Verschlüsselung | +|------|----------------|----------------|----------|-----------------| +| `rsync` | Schnell | Ja | SSH | Via SSH | +| `scp` | Mittel | Nein | SSH | Ja | +| `cp` | Sehr schnell | Nein | Nein | Nein | +| `tar` | Mittel | Nein | Pipe möglich | Optional | + +## Monitoring + +### Fortschritt detailliert + +```bash +rsync -av --progress --stats quelle/ ziel/ +``` + +### Nur Zusammenfassung + +```bash +rsync -av --stats quelle/ ziel/ +``` + +## Siehe auch + +- [[tar]] - Archive erstellen +- [[find]] - Dateien für Backup finden +- [[Symlinks]] - Links bleiben mit -a erhalten +- [[Dateiberechtigungen]] - Rechte und Eigentümer nach rsync +- [[ls]] - Übertragene Dateien anzeigen diff --git a/Computerkram/Linux/BASH Basics/sed.md b/Computerkram/Linux/BASH Basics/sed.md new file mode 100644 index 0000000..bc8353d --- /dev/null +++ b/Computerkram/Linux/BASH Basics/sed.md @@ -0,0 +1,270 @@ +# sed - Stream Editor + +Der `sed`-Befehl ist ein Stream-Editor für Textmanipulation. Er eignet sich besonders für Suchen-und-Ersetzen-Operationen. + +## Grundsyntax + +```bash +sed [OPTIONEN] 'BEFEHL' [DATEI...] +``` + +## Suchen und Ersetzen + +### Grundlegendes Ersetzen + +```bash +sed 's/alt/neu/' datei.txt +``` + +Ersetzt erste Vorkommen in jeder Zeile. + +### Alle Vorkommen in Zeile + +```bash +sed 's/alt/neu/g' datei.txt +``` + +- `g` = global (alle Vorkommen) + +### Datei direkt ändern + +```bash +sed -i 's/alt/neu/g' datei.txt +``` + +- `-i` = in-place (Datei wird geändert) + +### Backup vor Änderung + +```bash +sed -i.bak 's/alt/neu/g' datei.txt +``` + +Erstellt `datei.txt.bak` vor Änderung. + +## Zeilen auswählen + +### Bestimmte Zeile + +```bash +sed -n '5p' datei.txt # Nur Zeile 5 +sed '5d' datei.txt # Zeile 5 löschen +sed '5s/alt/neu/' datei.txt # Nur in Zeile 5 ersetzen +``` + +### Zeilenbereich + +```bash +sed -n '10,20p' datei.txt # Zeilen 10-20 anzeigen +sed '10,20d' datei.txt # Zeilen 10-20 löschen +``` + +### Letzte Zeile + +```bash +sed -n '$p' datei.txt # Letzte Zeile +``` + +### Muster-basiert + +```bash +sed '/^#/d' datei.txt # Zeilen mit # am Anfang löschen +sed '/ERROR/s/foo/bar/' datei.txt # Nur in Zeilen mit ERROR +``` + +## Zeilen einfügen und anhängen + +### Vor Zeile einfügen + +```bash +sed '3i\Neue Zeile' datei.txt +``` + +### Nach Zeile anhängen + +```bash +sed '3a\Neue Zeile' datei.txt +``` + +### Nach Muster + +```bash +sed '/TODO/a\WICHTIG: Bitte bearbeiten' datei.txt +``` + +## Zeilen löschen + +### Leere Zeilen + +```bash +sed '/^$/d' datei.txt +``` + +### Kommentare + +```bash +sed '/^#/d' datei.txt +``` + +### Mehrere Muster + +```bash +sed -e '/^#/d' -e '/^$/d' datei.txt +``` + +## Reguläre Ausdrücke + +### Erweiterte Regex + +```bash +sed -E 's/[0-9]{3}-[0-9]{4}/XXX-XXXX/g' datei.txt +``` + +- `-E` = Extended Regex + +### Gruppen und Backreferences + +```bash +sed 's/\([0-9]*\)-\([0-9]*\)/\2-\1/' datei.txt +``` + +Vertauscht Zahlen vor und nach Bindestrich. + +Mit `-E`: + +```bash +sed -E 's/([0-9]*)-([0-9]*)/\2-\1/' datei.txt +``` + +## Praktische Beispiele + +### Konfigurationsdatei ändern + +```bash +sed -i 's/^#Port 22/Port 2222/' /etc/ssh/sshd_config +``` + +### IP-Adressen ersetzen + +```bash +sed 's/192\.168\.1\./10.0.0./g' config.txt +``` + +### Zeilennummern hinzufügen + +```bash +sed = datei.txt | sed 'N;s/\n/\t/' +``` + +### Kommentare und Leerzeilen entfernen + +```bash +sed -e '/^#/d' -e '/^$/d' config.conf +``` + +### Mehrere Ersetzungen + +```bash +sed -e 's/foo/bar/g' -e 's/alt/neu/g' datei.txt +``` + +### Case-insensitive Suche + +```bash +sed 's/fehler/ERROR/gI' datei.txt +``` + +- `I` = case-insensitive + +### Zeilen mit Muster extrahieren + +```bash +sed -n '/ERROR/p' logfile.txt +``` + +Zeigt nur Zeilen mit "ERROR". + +### Text zwischen Mustern + +```bash +sed -n '/START/,/END/p' datei.txt +``` + +### Zeilen nummerieren + +```bash +sed = datei.txt +``` + +## Mit Pipes + +```bash +cat datei.txt | sed 's/alt/neu/g' | grep wichtig +ps aux | sed -n '1p;/firefox/p' +``` + +## Mehrere Dateien + +```bash +sed -i 's/alt/neu/g' *.txt +``` + +## Sed-Skripte + +**script.sed:** +```sed +# Kommentare entfernen +/^#/d +# Leerzeilen entfernen +/^$/d +# foo durch bar ersetzen +s/foo/bar/g +``` + +Verwenden: + +```bash +sed -f script.sed datei.txt +``` + +## Fehler vermeiden + +### Backup erstellen + +```bash +sed -i.bak 's/alt/neu/g' wichtig.txt +``` + +### Testen ohne Änderung + +```bash +sed 's/alt/neu/g' datei.txt > test.txt +diff datei.txt test.txt +``` + +### Spezialzeichen escapen + +```bash +# Punkt ist Wildcard +sed 's/192.168.1.1/10.0.0.1/' config # FALSCH + +# Punkt escapen +sed 's/192\.168\.1\.1/10.0.0.1/' config # RICHTIG +``` + +## Alternative Delimiter + +Wenn Pfade mit `/` vorkommen: + +```bash +sed 's|/old/path|/new/path|g' datei.txt +``` + +Statt `/` kann `|`, `#` oder andere Zeichen verwendet werden. + +## Siehe auch + +- [[grep]] - Textsuche +- [[awk]] - Komplexere Textverarbeitung +- [[find]] - Dateien finden und mit sed bearbeiten +- [[BASH Funktionen]] - sed in Funktionen verwenden diff --git a/Computerkram/Linux/BASH Basics/tar.md b/Computerkram/Linux/BASH Basics/tar.md new file mode 100644 index 0000000..00c8674 --- /dev/null +++ b/Computerkram/Linux/BASH Basics/tar.md @@ -0,0 +1,354 @@ +# tar - Archive erstellen und Software installieren + +Der `tar`-Befehl (tape archive) erstellt und entpackt Archive. Oft in Kombination mit Kompression (gzip, bzip2, xz). + +## Grundsyntax + +```bash +tar [OPTIONEN] [ARCHIV] [DATEIEN...] +``` + +## Archive erstellen + +### Einfaches Archiv (unkomprimiert) + +```bash +tar -cf archiv.tar verzeichnis/ +``` + +- `-c` = create (erstellen) +- `-f` = file (Dateiname) + +### Mit gzip-Kompression (.tar.gz) + +```bash +tar -czf archiv.tar.gz verzeichnis/ +``` + +- `-z` = gzip + +### Mit bzip2-Kompression (.tar.bz2) + +```bash +tar -cjf archiv.tar.bz2 verzeichnis/ +``` + +- `-j` = bzip2 + +### Mit xz-Kompression (.tar.xz) + +```bash +tar -cJf archiv.tar.xz verzeichnis/ +``` + +- `-J` = xz (beste Kompression) + +### Mit Fortschrittsanzeige + +```bash +tar -czf archiv.tar.gz verzeichnis/ -v +``` + +- `-v` = verbose (Details anzeigen) + +## Archive entpacken + +### Automatische Kompressionserkennung + +```bash +tar -xf archiv.tar.gz +``` + +- `-x` = extract (entpacken) + +### In bestimmtes Verzeichnis + +```bash +tar -xf archiv.tar.gz -C /ziel/verzeichnis +``` + +### Mit Fortschrittsanzeige + +```bash +tar -xvf archiv.tar.gz +``` + +## Archiv-Inhalt anzeigen + +```bash +tar -tf archiv.tar.gz +``` + +- `-t` = list (auflisten) + +Mit Details: + +```bash +tar -tvf archiv.tar.gz +``` + +## Praktische Beispiele + +### Backup erstellen + +```bash +tar -czf backup-$(date +%Y%m%d).tar.gz /home/user/dokumente +``` + +### Bestimmte Dateien ausschließen + +```bash +tar -czf archiv.tar.gz --exclude='*.tmp' --exclude='.git' verzeichnis/ +``` + +### Nur bestimmte Dateien hinzufügen + +```bash +tar -czf logs.tar.gz /var/log/*.log +``` + +### Zu bestehendem Archiv hinzufügen + +```bash +tar -rf archiv.tar neue_datei.txt +``` + +**Hinweis:** Funktioniert nur bei unkomprimierten Archiven! + +### Einzelne Datei aus Archiv extrahieren + +```bash +tar -xzf archiv.tar.gz pfad/zur/datei.txt +``` + +### Archiv auf andere Maschine übertragen + +```bash +tar -czf - verzeichnis/ | ssh user@server "cd /ziel && tar -xzf -" +``` + +## Dateirechte bewahren + +```bash +tar -czpf archiv.tar.gz verzeichnis/ +``` + +- `-p` = preserve permissions + +Als Root entpacken und Eigentümer bewahren: + +```bash +sudo tar -xpf archiv.tar.gz +``` + +## Inkrementelles Backup + +```bash +tar -czf backup-full.tar.gz -g snapshot.file verzeichnis/ +tar -czf backup-incr.tar.gz -g snapshot.file verzeichnis/ +``` + +- `-g` = incremental (inkrementell) + +## Geschwindigkeit vs. Kompression + +| Format | Geschwindigkeit | Kompression | Empfehlung | +|--------|----------------|-------------|------------| +| `.tar` | Sehr schnell | Keine | Lokale Kopien | +| `.tar.gz` | Schnell | Gut | Standard | +| `.tar.bz2` | Mittel | Besser | Archivierung | +| `.tar.xz` | Langsam | Beste | Langzeit-Archiv | + +## Fehler vermeiden + +### Führenden Slash entfernen + +```bash +tar -czf archiv.tar.gz --absolute-names /home/user/dokumente # Mit / +tar -czf archiv.tar.gz -C /home/user dokumente # Ohne / +``` + +Zweite Variante ist sicherer beim Entpacken. + +### Große Archive + +Prüfe Speicherplatz vorher: + +```bash +du -sh verzeichnis/ +df -h . +``` + +### Testen vor Löschen + +```bash +tar -czf backup.tar.gz daten/ +tar -tzf backup.tar.gz | head # Inhalt prüfen +# Erst dann löschen: +rm -rf daten/ +``` + +## Mit Verschlüsselung + +```bash +# Erstellen und verschlüsseln +tar -czf - verzeichnis/ | gpg -c > archiv.tar.gz.gpg + +# Entschlüsseln und entpacken +gpg -d archiv.tar.gz.gpg | tar -xzf - +``` + +## Software aus tar.gz installieren + +Eine `.tar.gz`-Datei kann verschiedene Inhalte haben: + +1. **Quellcode** → muss kompiliert werden +2. **Kompilierte Binaries** → nur entpacken und ausführen +3. **Paket für Distribution** → mit Paketmanager installieren + +### Archiv entpacken und untersuchen + +```bash +tar -xvzf paket.tar.gz +cd paket +ls -la +``` + +Prüfe immer `README`, `INSTALL` oder `INSTALL.txt`: + +```bash +cat README +cat INSTALL +``` + +### Installation aus Quellcode + +**Voraussetzungen installieren:** + +Debian/Ubuntu: +```bash +sudo apt install build-essential +``` + +Fedora: +```bash +sudo dnf groupinstall "Development Tools" +``` + +**Standard-Kompilierung (autotools):** +```bash +./configure +make +sudo make install +``` + +**CMake-basierte Projekte:** +```bash +mkdir build +cd build +cmake .. +make +sudo make install +``` + +### Installation von fertigen Binaries + +Wenn das Archiv fertige Programme enthält: + +```bash +chmod +x programmname +./programmname +``` + +Permanent installieren nach `/usr/local/bin`: + +```bash +sudo cp programmname /usr/local/bin/ +``` + +Oder nach `~/.local/bin` (ohne sudo): + +```bash +mkdir -p ~/.local/bin +cp programmname ~/.local/bin/ +``` + +Stelle sicher, dass `~/.local/bin` im PATH ist: + +```bash +echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc +source ~/.bashrc +``` + +### Deinstallation + +Bei selbst kompilierten Programmen: + +```bash +cd paket/ +sudo make uninstall +``` + +Falls `make uninstall` nicht verfügbar ist: + +**Mit checkinstall (empfohlen):** +```bash +sudo apt install checkinstall # Debian/Ubuntu + +# Statt "sudo make install" +sudo checkinstall + +# Später deinstallieren wie normales Paket +sudo apt remove paketname +``` + +**Manuell:** +```bash +# Liste der installierten Dateien erstellen +sudo make install > install.log 2>&1 + +# Zum Deinstallieren Dateien aus log löschen +``` + +### Beispiel-Workflow + +```bash +# 1. Entpacken +tar -xzf programm-1.0.tar.gz +cd programm-1.0 + +# 2. Dokumentation lesen +cat README +cat INSTALL + +# 3. Konfigurieren und kompilieren +./configure --prefix=/usr/local +make + +# 4. Optional: Tests ausführen +make check + +# 5. Installieren +sudo make install + +# 6. Testen +which programmname +programmname --version +``` + +### Typische Verzeichnisse + +Nach `make install` werden Dateien meist hier installiert: + +- `/usr/local/bin/` - Programme +- `/usr/local/lib/` - Bibliotheken +- `/usr/local/share/` - Daten/Dokumentation +- `/usr/local/etc/` - Konfiguration + +## Siehe auch + +- [[rsync]] - Alternative für Backups +- [[find]] - Dateien für Archivierung finden +- [[grep]] - Archiv-Inhalte durchsuchen +- [[Dateiberechtigungen]] - Rechte in Archiven bewahren +- [[ls]] - Archive anzeigen diff --git a/Computerkram/Linux/BASH Skripte/BASH Skript mit Argumenten und Weiterleitung.md b/Computerkram/Linux/BASH Skripte/BASH Skript mit Argumenten und Weiterleitung.md new file mode 100644 index 0000000..0b823b6 --- /dev/null +++ b/Computerkram/Linux/BASH Skripte/BASH Skript mit Argumenten und Weiterleitung.md @@ -0,0 +1,243 @@ +## Grundlegendes Vorgehen + +Ein BASH Skript, das Argumente verarbeitet und weiterleitet, folgt diesem Muster: + +```bash +#!/bin/bash + +# Standardwerte definieren +DEFAULT_VALUE="standard" +VERBOSE=false +TARGET_SCRIPT="./target-script.sh" + +# Argumente parsen +while [[ $# -gt 0 ]]; do + case $1 in + -v|--verbose) + VERBOSE=true + shift + ;; + -f|--file) + FILE="$2" + shift 2 + ;; + -o|--output) + OUTPUT="${2:-$DEFAULT_VALUE}" + shift 2 + ;; + -h|--help) + show_help + exit 0 + ;; + *) + # Unbekannte Argumente sammeln + UNKNOWN_ARGS+=("$1") + shift + ;; + esac +done + +# Alle Argumente an Zielskript weiterleiten +"$TARGET_SCRIPT" "${UNKNOWN_ARGS[@]}" +``` + +## Verschiedene Weiterleitungsstrategien + +### 1. Alle Argumente 1:1 weiterleiten +```bash +#!/bin/bash +./target-script.sh "$@" +``` + +### 2. Selektive Weiterleitung +```bash +#!/bin/bash + +# Lokale Verarbeitung +WRAPPER_OPTION="" +TARGET_ARGS=() + +while [[ $# -gt 0 ]]; do + case $1 in + --wrapper-only) + WRAPPER_OPTION="$2" + shift 2 + ;; + *) + TARGET_ARGS+=("$1") + shift + ;; + esac +done + +# Nur relevante Argumente weiterleiten +./target-script.sh "${TARGET_ARGS[@]}" +``` + +### 3. Argumente transformieren +```bash +#!/bin/bash + +TRANSFORMED_ARGS=() + +for arg in "$@"; do + case $arg in + --old-format) + TRANSFORMED_ARGS+=("--new-format") + ;; + *) + TRANSFORMED_ARGS+=("$arg") + ;; + esac +done + +./target-script.sh "${TRANSFORMED_ARGS[@]}" +``` + +## Erweiterte Techniken + +### Standardwerte und Validierung +```bash +#!/bin/bash + +# Standardwerte +CONFIG_FILE="${CONFIG_FILE:-/etc/default/myapp}" +LOG_LEVEL="${LOG_LEVEL:-INFO}" +DRY_RUN=false + +# Hilfsfunktion +show_help() { + cat << EOF +Usage: $0 [OPTIONS] -- [TARGET_ARGS] + +OPTIONS: + -c, --config FILE Konfigurationsdatei (default: $CONFIG_FILE) + -l, --log-level LVL Log Level (default: $LOG_LEVEL) + -n, --dry-run Nur Simulation + -h, --help Diese Hilfe + +Alle Argumente nach -- werden an das Zielskript weitergegeben. +EOF +} + +# Parsing mit -- Separator +TARGET_ARGS=() +PARSE_TARGET=false + +while [[ $# -gt 0 ]]; do + if [[ "$PARSE_TARGET" == true ]]; then + TARGET_ARGS+=("$1") + shift + continue + fi + + case $1 in + -c|--config) + CONFIG_FILE="$2" + shift 2 + ;; + -l|--log-level) + LOG_LEVEL="$2" + shift 2 + ;; + -n|--dry-run) + DRY_RUN=true + shift + ;; + -h|--help) + show_help + exit 0 + ;; + --) + PARSE_TARGET=true + shift + ;; + *) + echo "Unbekannte Option: $1" >&2 + show_help + exit 1 + ;; + esac +done + +# Validierung +if [[ ! -f "$CONFIG_FILE" ]]; then + echo "Konfigurationsdatei nicht gefunden: $CONFIG_FILE" >&2 + exit 1 +fi + +# Ausführung +if [[ "$DRY_RUN" == true ]]; then + echo "DRY RUN: ./target-script.sh ${TARGET_ARGS[*]}" +else + ./target-script.sh "${TARGET_ARGS[@]}" +fi +``` + +## Best Practices + +### 1. Sichere Argumentbehandlung +```bash +# Verwende Arrays für Argumente +ARGS=() +while IFS= read -r -d '' arg; do + ARGS+=("$arg") +done < <(printf '%s\0' "$@") + +# Sichere Weiterleitung +./target-script.sh "${ARGS[@]}" +``` + +### 2. Logging und Debugging +```bash +#!/bin/bash + +DEBUG=${DEBUG:-false} + +debug_log() { + if [[ "$DEBUG" == true ]]; then + echo "DEBUG: $*" >&2 + fi +} + +debug_log "Received arguments: $*" +debug_log "Passing to target: ${TARGET_ARGS[*]}" +``` + +### 3. Fehlerbehandlung +```bash +#!/bin/bash + +set -euo pipefail # Strict mode + +# Trap für Cleanup +cleanup() { + debug_log "Cleaning up..." +} +trap cleanup EXIT + +# Prüfe ob Zielskript existiert +if [[ ! -x "$TARGET_SCRIPT" ]]; then + echo "Fehler: Zielskript '$TARGET_SCRIPT' nicht gefunden oder nicht ausführbar" >&2 + exit 1 +fi + +# Führe aus und fange Exit-Code ab +if "$TARGET_SCRIPT" "$@"; then + debug_log "Zielskript erfolgreich ausgeführt" +else + exit_code=$? + echo "Zielskript fehlgeschlagen mit Exit-Code: $exit_code" >&2 + exit $exit_code +fi +``` + +## Verwandte Konzepte + +- [[Shell Scripting Best Practices]] +- [[BASH Argument Parsing]] +- [[Environment Variables in Shell Scripts]] + +--- + +**Tags**: #bash #scripting #arguments #shell #automation \ No newline at end of file diff --git a/Computerkram/Linux/BASH Skripte/Zugriff auf den Skript-Pfad in BASH.md b/Computerkram/Linux/BASH Skripte/Zugriff auf den Skript-Pfad in BASH.md new file mode 100644 index 0000000..70e985f --- /dev/null +++ b/Computerkram/Linux/BASH Skripte/Zugriff auf den Skript-Pfad in BASH.md @@ -0,0 +1,132 @@ +## Grundlegende Methoden + +### 1. Einfache Variante mit `$0` +```bash +#!/bin/bash +SCRIPT_PATH="$0" +echo "Skript wurde aufgerufen als: $SCRIPT_PATH" +``` + +### 2. Absoluter Pfad des Skripts +```bash +#!/bin/bash +SCRIPT_PATH="$(realpath "$0")" +echo "Absoluter Pfad des Skripts: $SCRIPT_PATH" +``` + +### 3. Verzeichnis des Skripts ermitteln +```bash +#!/bin/bash +SCRIPT_DIR="$(dirname "$(realpath "$0")")" +echo "Skript-Verzeichnis: $SCRIPT_DIR" +``` + +## Robuste Lösung für alle Szenarien + +```bash +#!/bin/bash + +# Funktion zur sicheren Ermittlung des Skript-Pfads +get_script_path() { + local source="${BASH_SOURCE[0]}" + + # Auflösung von Symlinks + while [ -h "$source" ]; do + local dir="$(cd -P "$(dirname "$source")" && pwd)" + source="$(readlink "$source")" + [[ $source != /* ]] && source="$dir/$source" + done + + echo "$(cd -P "$(dirname "$source")" && pwd)" +} + +SCRIPT_DIR="$(get_script_path)" +SCRIPT_NAME="$(basename "$0")" +SCRIPT_FULL_PATH="$SCRIPT_DIR/$SCRIPT_NAME" + +echo "Skript-Verzeichnis: $SCRIPT_DIR" +echo "Skript-Name: $SCRIPT_NAME" +echo "Vollständiger Pfad: $SCRIPT_FULL_PATH" +``` + +## Häufige Anwendungsfälle + +### Relative Pfade vom Skript-Verzeichnis aus +```bash +#!/bin/bash +SCRIPT_DIR="$(dirname "$(realpath "$0")")" + +# Zugriff auf andere Dateien relativ zum Skript +CONFIG_FILE="$SCRIPT_DIR/config.conf" +LOG_DIR="$SCRIPT_DIR/logs" + +# Prüfen ob Konfigurationsdatei existiert +if [ -f "$CONFIG_FILE" ]; then + echo "Konfiguration gefunden: $CONFIG_FILE" +fi +``` + +### Einbindung anderer Skripts +```bash +#!/bin/bash +SCRIPT_DIR="$(dirname "$(realpath "$0")")" + +# Andere Skripts aus dem gleichen Verzeichnis einbinden +source "$SCRIPT_DIR/common_functions.sh" +source "$SCRIPT_DIR/config.sh" +``` + +## Wichtige Unterschiede der Variablen + +| Variable | Beschreibung | Beispiel | +|----------|--------------|----------| +| `$0` | Aufruf-Name des Skripts | `./script.sh` oder `/path/script.sh` | +| `${BASH_SOURCE[0]}` | Tatsächlicher Pfad (auch bei sourcing) | `/absolute/path/script.sh` | +| `$(dirname "$0")` | Verzeichnis des Aufrufs | `.` oder `/path` | +| `$(realpath "$0")` | Absoluter, aufgelöster Pfad | `/absolute/path/script.sh` | + +## Besondere Situationen + +### Bei gesourcten Skripts +```bash +# In gesourcten Skripts sollten Sie BASH_SOURCE verwenden +SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" +``` + +### Bei Symlinks +```bash +# Auflösung von Symlinks +SCRIPT_PATH="$(readlink -f "$0")" +SCRIPT_DIR="$(dirname "$SCRIPT_PATH")" +``` + +## Praktisches Beispiel + +```bash +#!/bin/bash +# setup.sh - Installationsskript + +# Ermittlung des Skript-Verzeichnisses +SCRIPT_DIR="$(dirname "$(realpath "$0")")" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" + +echo "Starte Installation..." +echo "Skript-Verzeichnis: $SCRIPT_DIR" +echo "Projekt-Root: $PROJECT_ROOT" + +# Installation von Abhängigkeiten +pip install -r "$PROJECT_ROOT/requirements.txt" + +# Kopieren von Konfigurationsdateien +cp "$SCRIPT_DIR/templates/config.ini" "$PROJECT_ROOT/config/" + +echo "Installation abgeschlossen!" +``` + +## Tags +#bash #scripting #pfade #entwicklung + +## Verwandte Themen +- [[BASH Grundlagen]] +- [[Dateisystem Navigation]] +- [[Skript Entwicklung Best Practices]] \ No newline at end of file diff --git a/Computerkram/Linux/Boot Menü anpassen.md b/Computerkram/Linux/Boot Menü anpassen.md new file mode 100644 index 0000000..8870b5a --- /dev/null +++ b/Computerkram/Linux/Boot Menü anpassen.md @@ -0,0 +1,407 @@ +Diese Anleitung führt dich praxisnah durch die wichtigsten Bootloader unter Linux – **GRUB 2** (am weitesten verbreitet) und **systemd-boot** – und zeigt, wie du Menüeinträge ausblendest, die **Timeout-Zeit** änderst, den **Standard-Eintrag** festlegst, **Kernel-Parameter** setzt, Themes nutzt u. v. m. Am Ende findest du auch Tipps für UEFI-Bootreihenfolge, Dual-Boot und Fehlerbehebung. + +--- + +## 1) Welchen Bootloader habe ich – BIOS/UEFI? + +```bash +# UEFI oder BIOS? +[ -d /sys/firmware/efi ] && echo "UEFI" || echo "BIOS/Legacy" + +# GRUB oder systemd-boot? +bootctl status 2>/dev/null | grep -q 'systemd-boot' && echo "systemd-boot" || echo "GRUB (sehr wahrscheinlich)" +``` + +- **GRUB 2**: Standard bei Ubuntu, Debian, Fedora, openSUSE, Arch (sofern nicht umgestellt). + +- **systemd-boot**: Häufig bei minimalistischen Setups (Arch, Fedora/Silverblue, Pop!_OS, Manjaro-Varianten) – nur im UEFI-Modus. + + +> **Wichtig:** **Bearbeite nie direkt** die generierte Datei `/boot/grub/grub.cfg`. Änderungen gehören in `/etc/default/grub` (GRUB) bzw. `/boot/loader/loader.conf` + `…/entries/*.conf` (systemd-boot), und **danach** wird die Konfiguration neu generiert. + +--- + +## 2) GRUB 2 konfigurieren (die häufigste Variante) + +### 2.1 Ort der Einstellungen + +- Hauptdatei: `/etc/default/grub` + +- Menüeinträge (automatisch generiert): `/boot/grub/grub.cfg` + +- Regenerieren: + + - Debian/Ubuntu: `sudo update-grub` + + - Fedora/RHEL/openSUSE: + + - BIOS: `sudo grub2-mkconfig -o /boot/grub2/grub.cfg` + + - UEFI: `sudo grub2-mkconfig -o /boot/efi/EFI//grub.cfg` + + - Arch: `sudo grub-mkconfig -o /boot/grub/grub.cfg` + + +> Tipp: Mach vor Änderungen ein Backup: +> `sudo cp /etc/default/grub /etc/default/grub.bak.$(date +%F)` + +### 2.2 Zeit bis zur automatischen Auswahl (Timeout) + +In `/etc/default/grub` anpassen: + +```ini +GRUB_TIMEOUT=2 # Sekunden bis Autostart +GRUB_TIMEOUT_STYLE=menu # "hidden" blendet das Menü aus (siehe unten) +``` + +- **Menü ausblenden**: + + ```ini + GRUB_TIMEOUT_STYLE=hidden + GRUB_TIMEOUT=0 + ``` + + -> System bootet sofort, Menü erscheint **nur** wenn du beim Einschalten **Shift (BIOS)** oder **Esc (UEFI)** gedrückt hältst (je nach Firmware/Distro). + +- **Menü immer zeigen**: + + ```ini + GRUB_TIMEOUT_STYLE=menu + GRUB_TIMEOUT=5 + ``` + + +Danach Konfiguration neu generieren (siehe 2.1). + +### 2.3 Standard-Eintrag festlegen + +Variante A – fester Index (0-basierend, **ändert sich bei Kernel-Updates ggf.**): + +```ini +GRUB_DEFAULT=0 +``` + +Variante B – per Name (stabiler): + +```ini +GRUB_DEFAULT="Advanced options for Ubuntu>Ubuntu, with Linux 6.10.5" +``` + +Variante C – „zuletzt gebooteten“ Eintrag merken: + +```ini +GRUB_DEFAULT=saved +GRUB_SAVEDEFAULT=true +``` + +Einmalig einen anderen Eintrag für den **nächsten** Boot setzen: + +```bash +sudo grub-reboot "Ubuntu, with Linux 6.10.5" +# oder nach Index: +sudo grub-reboot 2 +``` + +### 2.4 Kernel-Parameter setzen (leiser, schneller, NVIDIA, etc.) + +In `/etc/default/grub`: + +```ini +GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" +GRUB_CMDLINE_LINUX="resume=UUID= mitigations=auto" +``` + +Häufige Parameter: + +- `quiet splash` – leiser Boot mit Grafiksplash (Plymouth). + +- `nomodeset` – Notfall bei Grafiktreibern. + +- `nowatchdog` – schaltet Watchdogs aus (Debug/Workarounds). + +- `acpi_osi=` / `acpi_backlight=` – Backlight-Probleme bei Laptops. + +- `amd_pstate=active` / `intel_pstate=` – CPU-Scaling steuern. + +- `mitigations=off` (nur Test!) – Sicherheits-Mitigations deaktivieren. + + +> Nach Änderung immer Konfiguration regenerieren (2.1). + +### 2.5 Einträge ausblenden / aufräumen + +- **Andere OS suchen (Dual-Boot)** wird teils aus Sicherheitsgründen deaktiviert. Falls Windows fehlt: + + ```ini + GRUB_DISABLE_OS_PROBER=false + ``` + + Danach: + + ```bash + sudo update-grub # bzw. grub2-mkconfig ... + ``` + +- Bestimmte **Recovery-Einträge** ausblenden: In vielen Distros via Paket `grub-customizer` oder durch eigene Skripte unter `/etc/grub.d/` (fortgeschritten). + Minimal: Notfalls Einträge in `/etc/grub.d/40_custom` definieren und Standardliste ausblenden (nicht empfohlen, weil Updates überschreiben können). + + +### 2.6 Themes, Auflösung und Optik + +In `/etc/default/grub`: + +```ini +GRUB_GFXMODE=1920x1080 +GRUB_GFXPAYLOAD_LINUX=keep +GRUB_THEME="/boot/grub/themes/mein-theme/theme.txt" +``` + +- Auflösung prüfen: In der GRUB-Konsole `videoinfo` eintippen (interaktiv). + +- Themes bekommst du aus Paketquellen (z. B. `grub-theme-*`) oder GitHub. Theme in `/boot/grub/themes/...` ablegen. + + +### 2.7 Sonderfälle (UEFI-Pfad, BIOS, LUKS, Btrfs) + +- **UEFI**: Achte beim `grub2-mkconfig` auf den richtigen **Ausgabepfad** (siehe 2.1). + +- **Vollverschlüsselt (LUKS)**: Kernel-Parameter und initramfs müssen passen (meist automatisch korrekt). + +- **Btrfs-Snapshots** (z. B. mit Snapper): Paket **grub-btrfs** integriert Snapshots ins Menü. + +- **Sichere Bootreihenfolge**: Siehe Abschnitt 4 (efibootmgr). + + +--- + +## 3) systemd-boot konfigurieren (UEFI-Only, sehr schlank) + +### 3.1 Dateien & Struktur + +- Hauptdatei: `/boot/loader/loader.conf` + +- Einträge: `/boot/loader/entries/*.conf` (eine Datei pro Eintrag) + +- Kernel/Initrd liegen meist unter `/boot` oder `/efi`. + + +### 3.2 Menü ausblenden, Timeout, Standard + +`/boot/loader/loader.conf`: + +```ini +timeout 2 # Sekunden (0 = sofort) +default arch # oder: @saved +editor no # verhindert Bearbeiten im Menü +console-mode auto # Grafikmodus: auto, 0..4 +``` + +- **Menü ausblenden**: `timeout 0` + -> Menü erscheint bei **gedrückter Leertaste** oder wenn mehrere Einträge vorhanden sind (je nach Firmware/Distribution). + +- **Zuletzt gebooteten Eintrag merken**: `default @saved` + Beim Booten auswählen; systemd-boot speichert die Wahl in `loader/`. + + +### 3.3 Einträge bearbeiten + +Beispiel `/boot/loader/entries/arch.conf`: + +```ini +title Arch Linux +linux /vmlinuz-linux +initrd /initramfs-linux.img +options root=UUID= rw quiet splash +``` + +- **Kernel-Parameter** hängst du einfach an `options` an. + +- Mehrere `initrd` Zeilen sind erlaubt (z. B. Microcode + initramfs). + + +### 3.4 Kernel installieren/aktualisieren + +- Viele Distros nutzen `kernel-install` Hooks, die automatisch passende `entries/*.conf` erzeugen. + +- Ansonsten Einträge manuell pflegen (simpel und transparent). + + +--- + +## 4) UEFI-Bootreihenfolge & Dual-Boot + +### 4.1 Bootreihenfolge mit `efibootmgr` + +Liste anzeigen: + +```bash +sudo efibootmgr +``` + +Reihenfolge setzen (Beispiel, IDs anpassen): + +```bash +sudo efibootmgr -o 0003,0001,0002 +``` + +**GRUB** oder **systemd-boot** sollte ganz vorn stehen. +Ein einzelnes Boot-Target (z. B. Windows) **einmalig** booten: + +```bash +sudo efibootmgr -n 0002 +``` + +### 4.2 Windows fehlt im Menü? + +- Bei **GRUB**: `GRUB_DISABLE_OS_PROBER=false` (siehe 2.5) und neu generieren. + +- Bei **systemd-boot**: eigenen `windows.conf` Eintrag unter `entries/` anlegen oder die automatische Erkennung der Distribution nutzen. + + +--- + +## 5) Häufige Aufgaben – Schritt-für-Schritt + +### A) Menü ausblenden & Sofort-Boot (GRUB) + +1. `sudo nano /etc/default/grub` + +2. Setze: + + ```ini + GRUB_TIMEOUT_STYLE=hidden + GRUB_TIMEOUT=0 + ``` + +3. `sudo update-grub` (oder passendes `grub*-mkconfig`) + +4. Test: Reboot, ggf. **Shift/Esc** halten, um das Menü zu zeigen. + + +### B) Timeout auf 5 s und Standard-Kernel merken (GRUB) + +1. `/etc/default/grub`: + + ```ini + GRUB_TIMEOUT_STYLE=menu + GRUB_TIMEOUT=5 + GRUB_DEFAULT=saved + GRUB_SAVEDEFAULT=true + ``` + +2. Regenerieren. + +3. Nächster Boot merkt sich deine Auswahl automatisch. + + +### C) Ruhiger, schneller Boot mit Splash (GRUB) + +1. `/etc/default/grub`: + + ```ini + GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" + ``` + +2. Optional Plymouth-Theme installieren. + +3. Regenerieren und neu starten. + + +### D) systemd-boot: Menü 1 s, zuletzt Gebootetes merken + +1. `sudoedit /boot/loader/loader.conf`: + + ```ini + timeout 1 + default @saved + editor no + ``` + +2. Reboot, Auswahl wird gemerkt. + + +--- + +## 6) Sicherheit, Recovery & Wartung + +- **Secure Boot**: Mit GRUB in der Regel via `shim` signiert – bei eigenen Kernel/Modulen ggf. MOK-Signatur nötig. systemd-boot lädt nur signierte Images, wenn Secure Boot aktiv ist. + +- **Recovery-Pfad**: Halte mindestens einen **nicht-minimalen** Kernel-Eintrag ohne aggressive Parameter bereit (ohne `nomodeset`, ohne `mitigations=off` etc.). + +- **Backups**: Sichere `/etc/default/grub`, `loader.conf` und eigene `entries/*.conf`. + +- **Fallback-Boot**: Notiere einen **UEFI-One-Shot** Befehl (`efibootmgr -n `), falls das Menü einmal nicht erscheint. + + +--- + +## 7) Troubleshooting (schnelle Checks) + +- GRUB-Menü erscheint nicht: + + - Firmware zeigt direkt Windows → Reihenfolge mit `efibootmgr` korrigieren. + + - `GRUB_TIMEOUT_STYLE=hidden`? → Temporär **Shift/Esc** beim Start. + +- Neue Kernel erscheinen nicht: + + - Nach Updates `update-grub` / `grub*-mkconfig` ausgeführt? + + - Pfad für UEFI-Ausgabe korrekt? + +- Dual-Boot-Einträge fehlen: + + - `os-prober` aktivieren (`GRUB_DISABLE_OS_PROBER=false`), dann neu generieren. + +- Schwarzer Bildschirm nach Grafiktreiber-Wechsel: + + - Temporär `nomodeset` im Bootmenü ergänzen (e), dann dauerhaft in `GRUB_CMDLINE_LINUX_DEFAULT`. + + +--- + +## 8) Nützliche Befehle (Cheatsheet) + +```bash +# GRUB neu generieren (Debian/Ubuntu) +sudo update-grub + +# GRUB neu generieren (UEFI, Fedora-Beispiel) +sudo grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg + +# Standard-Eintrag nur für den nächsten Boot (GRUB) +sudo grub-reboot 2 +sudo grub-reboot "Advanced options for Ubuntu>Ubuntu, with Linux 6.10.5" + +# Zuletzt gebooteten Eintrag merken (Konfig siehe oben) +# -> einfach normal auswählen; GRUB speichert es. + +# systemd-boot Status +bootctl status + +# UEFI Boots verwalten +sudo efibootmgr +sudo efibootmgr -o 0003,0001,0002 +sudo efibootmgr -n 0002 # One-shot + +# Welche Auflösungen unterstützt GRUB? +# (in GRUB-Konsole: drücke 'c', dann) +videoinfo +``` + +--- + +## 9) Empfehlung nach Use-Case + +- **Einsteiger / klassische Desktop-Distro** → **GRUB 2** beibehalten, Timeout 2–5 s, `saved`-Default, `quiet splash`. + +- **Schlanke, transparente Setups (UEFI)** → **systemd-boot**: `timeout 1`, `default @saved`. + +- **Dual-Boot mit Windows** → GRUB 2 + `os-prober` aktivieren; in UEFI die Reihenfolge mit `efibootmgr` sichern. + +- **Schneller „kioskartiger“ Boot** → Menü verstecken (`hidden/0` bzw. `timeout 0`) und Hotkey kennen (Shift/Esc/Leertaste). + + +--- + +Wenn du mir deine Distribution und dein Ziel (z. B. „Menü vollständig verstecken“, „Windows hinzufügen“, „Splash aktivieren“) nennst, schreibe ich dir die **exakten** Befehle für dein System in einem kleinen, kopierfertigen Block. \ No newline at end of file diff --git a/Computerkram/Linux/Bootfähigen USB-Stick mit `dd` erstellen.md b/Computerkram/Linux/Bootfähigen USB-Stick mit `dd` erstellen.md new file mode 100644 index 0000000..d4bf171 --- /dev/null +++ b/Computerkram/Linux/Bootfähigen USB-Stick mit `dd` erstellen.md @@ -0,0 +1,85 @@ +Alles klar 👍 – hier eine **allgemeine Schritt-für-Schritt-Anleitung**, wie du unter [[Linux]] mit `dd` einen **bootfähigen USB-Stick aus _beliebigen_ ISO-Dateien** erstellst: + +--- + +## 🔹 Bootfähigen USB-Stick mit `dd` erstellen + +### 1. ISO-Datei bereitlegen + +Speichere die ISO-Datei in einem bekannten Pfad, z. B.: + +``` +~/Downloads/dein.iso +``` + +--- + +### 2. USB-Stick einstecken und Gerät identifizieren + +Liste alle Laufwerke: + +```bash +lsblk +``` + +oder + +```bash +sudo fdisk -l +``` + +Beispielausgabe: + +``` +sda 500G # deine interne Festplatte +sdb 16G # dein USB-Stick +``` + +👉 Der Stick ist hier `/dev/sdb`. +⚠️ Wichtig: **Niemals eine Partition (z. B. `/dev/sdb1`) wählen, immer das ganze Gerät (`/dev/sdb`).** + +--- + +### 3. ISO auf den Stick schreiben + +Ersetze die Platzhalter: + +```bash +sudo dd if=/pfad/zur/datei.iso of=/dev/sdX bs=4M status=progress oflag=sync +``` + +- `if=` → Pfad zur ISO-Datei (z. B. `~/Downloads/dein.iso`) + +- `of=` → dein USB-Gerät (z. B. `/dev/sdb`) + +- `bs=4M` → Blockgröße, sorgt für schnelleres Schreiben + +- `status=progress` → zeigt den Fortschritt + +- `oflag=sync` → sorgt für sauberes Schreiben + + +**Beispiel:** + +```bash +sudo dd if=~/Downloads/bazzite.iso of=/dev/sdb bs=4M status=progress oflag=sync +``` + +--- + +### 4. Schreibvorgang abschließen + +Bevor du den Stick abziehst: + +```bash +sync +sudo eject /dev/sdb +``` + +--- + +### 5. Stick zum Booten nutzen + +Jetzt kannst du den Stick in den Zielrechner stecken, im BIOS/UEFI den Stick auswählen und davon booten. + +--- diff --git a/Computerkram/Linux/Disable KVM for VirtualBox.md b/Computerkram/Linux/Disable KVM for VirtualBox.md new file mode 100644 index 0000000..39bc78f --- /dev/null +++ b/Computerkram/Linux/Disable KVM for VirtualBox.md @@ -0,0 +1,76 @@ +How can I disable the [[kvm]] Kernel in [[Linux]], so that I can launch a virtual machine in VirtualBox + +--- +When you run [[VirtualBox]] on a Linux host, it can conflict with the **KVM kernel modules** (`kvm` and `kvm_intel` or `kvm_amd`). VirtualBox doesn’t use KVM, and if those modules are loaded, they can prevent VirtualBox VMs from starting properly. + +To disable KVM, you can either **temporarily unload** the modules or **permanently blacklist** them. + +--- + +### 🔹 Option 1: Temporarily Disable KVM + +Run the following commands (with root privileges): + +```bash +sudo modprobe -r kvm_intel +sudo modprobe -r kvm_amd +sudo modprobe -r kvm +``` + +- If your CPU is Intel, unload `kvm_intel`. + +- If your CPU is AMD, unload `kvm_amd`. + +- Then unload the generic `kvm` module. + + +This will disable KVM until the next reboot. + +--- + +### 🔹 Option 2: Permanently Disable KVM + +To prevent KVM from loading on boot, blacklist the modules: + +1. Create a blacklist file: + + ```bash + sudo nano /etc/modprobe.d/blacklist-kvm.conf + ``` + +2. Add these lines: + + ``` + blacklist kvm + blacklist kvm_intel + blacklist kvm_amd + ``` + +3. Save and exit. + +4. Update initramfs (on some distros, required): + + ```bash + sudo update-initramfs -u + ``` + +5. Reboot your system. + + +--- + +### 🔹 Verify + +After reboot (or unloading), check that no KVM modules are loaded: + +```bash +lsmod | grep kvm +``` + +If the output is empty, KVM is disabled and VirtualBox should work. + +--- + +⚠️ **Note:** If you ever want to use QEMU/KVM again, you’ll need to remove those blacklist entries and reboot. + +Would you like me to also show you how to make VirtualBox auto-unload KVM just when you launch a VM (without disabling it system-wide)? That way, you can keep using both VirtualBox and KVM on the same system. \ No newline at end of file diff --git a/Computerkram/Linux/Displaylink Installation.md b/Computerkram/Linux/Displaylink Installation.md new file mode 100644 index 0000000..b94fff3 --- /dev/null +++ b/Computerkram/Linux/Displaylink Installation.md @@ -0,0 +1,418 @@ +Hier ist ein umfassendes Shell-Skript für die Installation von DisplayLink-Treibern unter Linux: + +```bash +#!/bin/bash + +# DisplayLink Driver Installation Script for Linux +# Author: Assistant +# Version: 1.0 +# Date: $(date +%Y-%m-%d) + +set -e + +# Farben für Output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Logging +LOG_FILE="/var/log/displaylink-install.log" +exec > >(tee -a "$LOG_FILE") +exec 2>&1 + +echo -e "${BLUE}========================================${NC}" +echo -e "${BLUE} DisplayLink Driver Installation Script${NC}" +echo -e "${BLUE}========================================${NC}" + +# Funktionen +log() { + echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] INFO: $1${NC}" +} + +warn() { + echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] WARNING: $1${NC}" +} + +error() { + echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1${NC}" +} + +check_root() { + if [[ $EUID -ne 0 ]]; then + error "Dieses Skript muss als root ausgeführt werden!" + exit 1 + fi +} + +detect_distro() { + if [ -f /etc/os-release ]; then + . /etc/os-release + DISTRO=$ID + VERSION=$VERSION_ID + log "Distribution erkannt: $PRETTY_NAME" + else + error "Distribution konnte nicht erkannt werden" + exit 1 + fi +} + +install_dependencies() { + log "Installiere benötigte Abhängigkeiten..." + + case $DISTRO in + ubuntu|debian) + apt update + apt install -y wget curl unzip dkms build-essential \ + linux-headers-$(uname -r) git libdrm-dev \ + x11-xserver-utils mesa-utils + ;; + fedora|centos|rhel) + if command -v dnf &> /dev/null; then + dnf install -y wget curl unzip dkms gcc make \ + kernel-devel-$(uname -r) git libdrm-devel \ + xrandr mesa-utils + else + yum install -y wget curl unzip dkms gcc make \ + kernel-devel-$(uname -r) git libdrm-devel \ + xrandr mesa-utils + fi + ;; + opensuse*) + zypper install -y wget curl unzip dkms gcc make \ + kernel-default-devel git libdrm-devel \ + xrandr Mesa-utils + ;; + arch|manjaro) + pacman -Sy --noconfirm wget curl unzip dkms base-devel \ + linux-headers git libdrm xorg-xrandr mesa-utils + ;; + *) + warn "Unbekannte Distribution. Versuche generische Installation..." + ;; + esac +} + +download_displaylink_driver() { + log "Lade neueste DisplayLink-Treiber herunter..." + + # Erstelle temporäres Verzeichnis + TEMP_DIR=$(mktemp -d) + cd "$TEMP_DIR" + + # DisplayLink Download URL (Ubuntu 22.04 kompatibel) + DRIVER_VERSION="5.8.0-63.33" + DRIVER_URL="https://www.synaptics.com/sites/default/files/Ubuntu/pool/stable/main/all/synaptics-repository-keyring.deb" + + # Alternative: Verwende evdi Repository + log "Installiere EVDI (Extensible Virtual Display Interface)..." + git clone https://github.com/DisplayLink/evdi.git + cd evdi + make && make install + cd .. + + # Offizieller DisplayLink Treiber Download + OFFICIAL_URL="https://www.synaptics.com/sites/default/files/Ubuntu/pool/stable/main/all/" + + # Neueste verfügbare Version ermitteln + log "Ermittle neueste verfügbare Treiberversion..." + + # Fallback: Direkte Installation über Repository + case $DISTRO in + ubuntu|debian) + # Füge DisplayLink Repository hinzu + wget -O - https://www.synaptics.com/sites/default/files/Ubuntu/displaylink-debian-ubuntu-signing-key.pub | apt-key add - + echo "deb https://www.synaptics.com/sites/default/files/Ubuntu/ $(lsb_release -cs) stable" > /etc/apt/sources.list.d/displaylink.list + apt update + apt install -y displaylink-driver + ;; + *) + # Manuelle Installation für andere Distributionen + DRIVER_FILE="displaylink-driver-5.8.0-63.33.zip" + log "Lade $DRIVER_FILE herunter..." + + # Beispiel-Download (URL muss aktualisiert werden) + if ! wget -q --spider "https://www.displaylink.com/downloads/file?id=1768"; then + warn "Automatischer Download fehlgeschlagen. Manuelle Installation erforderlich." + log "Bitte laden Sie den neuesten Treiber von https://www.displaylink.com/downloads/ubuntu herunter" + return 1 + fi + ;; + esac +} + +install_displaylink_driver() { + log "Installiere DisplayLink-Treiber..." + + # Stoppe potentiell laufende Services + systemctl stop dlm.service 2>/dev/null || true + systemctl stop displaylink-driver.service 2>/dev/null || true + + case $DISTRO in + ubuntu|debian) + # Bereits über Repository installiert + log "Treiber über Repository installiert" + ;; + *) + # Manuelle Installation + if [ -f "displaylink-driver-*.run" ] || [ -f "DisplayLink*.run" ]; then + chmod +x DisplayLink*.run 2>/dev/null || chmod +x displaylink-driver-*.run + ./DisplayLink*.run --noexec --target displaylink-driver 2>/dev/null || ./displaylink-driver-*.run --noexec --target displaylink-driver + cd displaylink-driver + ./displaylink-installer.sh install + fi + ;; + esac + + # EVDI Modul laden + modprobe evdi || warn "EVDI Modul konnte nicht geladen werden" +} + +configure_services() { + log "Konfiguriere SystemD Services..." + + # DisplayLink Service aktivieren + systemctl enable dlm.service 2>/dev/null || systemctl enable displaylink-driver.service 2>/dev/null || true + + # Erstelle Custom Service falls nötig + if [ ! -f "/etc/systemd/system/displaylink.service" ]; then + cat > /etc/systemd/system/displaylink.service << EOF +[Unit] +Description=DisplayLink Manager Service +After=display-manager.service + +[Service] +Type=forking +ExecStartPre=/sbin/modprobe evdi +ExecStart=/opt/displaylink/DisplayLinkManager +ExecStop=/opt/displaylink/DisplayLinkManager --stop +Restart=always +RestartSec=5 + +[Install] +WantedBy=graphical.target +EOF + + systemctl daemon-reload + systemctl enable displaylink.service + fi +} + +fix_common_issues() { + log "Behebe bekannte Probleme..." + + # Problem 1: EVDI Modul beim Boot laden + if ! grep -q "evdi" /etc/modules; then + echo "evdi" >> /etc/modules + log "EVDI zu /etc/modules hinzugefügt" + fi + + # Problem 2: Xorg Konfiguration + mkdir -p /etc/X11/xorg.conf.d/ + cat > /etc/X11/xorg.conf.d/20-displaylink.conf << EOF +Section "OutputClass" + Identifier "DisplayLink" + MatchDriver "evdi" + Driver "modesetting" + Option "AccelMethod" "none" +EndSection +EOF + + # Problem 3: Udev Regeln + cat > /etc/udev/rules.d/99-displaylink.rules << EOF +# DisplayLink USB devices +ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", TAG+="systemd", ENV{SYSTEMD_WANTS}="displaylink.service" +ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="*", RUN+="/bin/systemctl start displaylink.service" +EOF + + udevadm control --reload-rules + + # Problem 4: Permissions + usermod -a -G plugdev $SUDO_USER 2>/dev/null || true + + # Problem 5: Wayland Kompatibilität (für GNOME) + if [ "$XDG_SESSION_TYPE" = "wayland" ]; then + warn "Wayland erkannt. DisplayLink funktioniert besser mit X11." + log "Erstelle GDM Custom Config für X11..." + + mkdir -p /etc/gdm3 + cat > /etc/gdm3/custom.conf << EOF +[daemon] +WaylandEnable=false +DefaultSession=gnome-xorg +EOF + fi +} + +check_installation() { + log "Überprüfe Installation..." + + # Service Status + if systemctl is-active --quiet dlm.service || systemctl is-active --quiet displaylink-driver.service || systemctl is-active --quiet displaylink.service; then + log "DisplayLink Service läuft erfolgreich" + else + warn "DisplayLink Service läuft nicht. Starte Service..." + systemctl start displaylink.service 2>/dev/null || systemctl start dlm.service 2>/dev/null || true + fi + + # Modul Status + if lsmod | grep -q evdi; then + log "EVDI Kernel Modul erfolgreich geladen" + else + warn "EVDI Kernel Modul nicht geladen. Versuche manuelles Laden..." + modprobe evdi || error "EVDI Modul konnte nicht geladen werden" + fi + + # USB Geräte check + if lsusb | grep -i displaylink; then + log "DisplayLink USB-Gerät erkannt" + else + warn "Kein DisplayLink USB-Gerät erkannt. Schließen Sie ein Gerät an." + fi +} + +create_troubleshooting_script() { + log "Erstelle Troubleshooting-Skript..." + + cat > /usr/local/bin/displaylink-troubleshoot << 'EOF' +#!/bin/bash + +echo "=== DisplayLink Troubleshooting ===" +echo "" + +echo "1. Service Status:" +systemctl status displaylink.service dlm.service displaylink-driver.service 2>/dev/null || echo "Services nicht gefunden" +echo "" + +echo "2. Kernel Module:" +lsmod | grep evdi || echo "EVDI Modul nicht geladen" +echo "" + +echo "3. USB Devices:" +lsusb | grep -i displaylink || echo "Keine DisplayLink Geräte gefunden" +echo "" + +echo "4. Displays:" +xrandr --listproviders 2>/dev/null || echo "Xrandr nicht verfügbar" +echo "" + +echo "5. Logs:" +journalctl -u displaylink.service --no-pager -n 10 2>/dev/null || echo "Keine Service Logs" +echo "" + +echo "=== Schnelle Fixes ===" +echo "Service neu starten:" +echo " sudo systemctl restart displaylink.service" +echo "" +echo "Modul neu laden:" +echo " sudo modprobe -r evdi && sudo modprobe evdi" +echo "" +echo "Display erkennung:" +echo " xrandr --setprovideroutputsource 1 0 && xrandr --auto" + +EOF + + chmod +x /usr/local/bin/displaylink-troubleshoot + log "Troubleshooting-Skript erstellt: /usr/local/bin/displaylink-troubleshoot" +} + +cleanup() { + log "Räume temporäre Dateien auf..." + cd / + rm -rf "$TEMP_DIR" 2>/dev/null || true +} + +main() { + log "Starte DisplayLink Installation..." + + check_root + detect_distro + install_dependencies + download_displaylink_driver + install_displaylink_driver + configure_services + fix_common_issues + check_installation + create_troubleshooting_script + cleanup + + echo -e "${GREEN}========================================${NC}" + echo -e "${GREEN} Installation abgeschlossen!${NC}" + echo -e "${GREEN}========================================${NC}" + echo "" + log "Installation erfolgreich abgeschlossen!" + log "Bitte starten Sie das System neu für beste Ergebnisse." + log "Bei Problemen verwenden Sie: displaylink-troubleshoot" + echo "" + echo -e "${YELLOW}Nächste Schritte:${NC}" + echo "1. System neu starten" + echo "2. DisplayLink Gerät anschließen" + echo "3. Monitor-Konfiguration mit: xrandr --auto" + echo "4. Bei Problemen: displaylink-troubleshoot ausführen" +} + +# Trap für Cleanup +trap cleanup EXIT + +# Hauptfunktion ausführen +main "$@" +``` + +## Zusätzliche Konfigurationsdateien + +### 1. Desktop-Shortcut für schnelle Display-Konfiguration: + +```bash +#!/bin/bash +# Erstelle Desktop-Shortcut +cat > ~/Desktop/configure-displays.desktop << EOF +[Desktop Entry] +Version=1.0 +Type=Application +Name=Configure DisplayLink Displays +Comment=Configure external displays via DisplayLink +Exec=bash -c 'xrandr --setprovideroutputsource 1 0 && xrandr --auto && notify-send "Displays konfiguriert"' +Icon=preferences-desktop-display +Terminal=false +Categories=System;Settings; +EOF + +chmod +x ~/Desktop/configure-displays.desktop +``` + +### 2. Automatische Display-Konfiguration bei USB-Anschluss: + +```bash +# Udev-Regel für automatische Konfiguration +cat > /etc/udev/rules.d/99-displaylink-autoconfig.rules << EOF +ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", RUN+="/usr/local/bin/displaylink-autoconfig.sh" +EOF + +# Autoconfig-Skript +cat > /usr/local/bin/displaylink-autoconfig.sh << 'EOF' +#!/bin/bash +sleep 3 +export DISPLAY=:0 +xrandr --setprovideroutputsource 1 0 +xrandr --auto +EOF + +chmod +x /usr/local/bin/displaylink-autoconfig.sh +``` + +## Verwendung: + +1. Skript als root ausführen: +```bash +sudo bash displaylink-install.sh +``` + +2. Nach der Installation System neu starten + +3. Bei Problemen Troubleshooting ausführen: +```bash +displaylink-troubleshoot +``` + +Das Skript automatisiert die komplette Installation und behebt die häufigsten Probleme mit DisplayLink-Treibern unter verschiedenen Linux-Distributionen. \ No newline at end of file diff --git a/Computerkram/Linux/Hyprland/Stow mit Logik.md b/Computerkram/Linux/Hyprland/Stow mit Logik.md new file mode 100644 index 0000000..ec403b7 --- /dev/null +++ b/Computerkram/Linux/Hyprland/Stow mit Logik.md @@ -0,0 +1,140 @@ +Kurz gesagt: **Nein – GNU Stow führt keine Skripte aus.** +Und das ist auch Absicht 🙂 + +GNU Stow macht **nur eine Sache**: + +> Es erzeugt und entfernt Symlinks. + +Keine Hooks. +Keine Post-Deploy-Skripte. +Keine Automatik. + +--- + +# 🧠 Warum ist das so? + +Stow ist bewusst: + +* minimalistisch +* deterministisch +* side-effect-frei + +Dadurch bleibt dein Setup transparent und reproduzierbar. + +--- + +# ✅ Aber: Man kann es kombinieren + +Wenn du beim „Deploy“ zusätzlich Dinge tun willst (z. B. Monitor-Symlink setzen, Pakete installieren, Cache leeren, etc.), gibt es saubere Lösungen: + +--- + +# 🔹 Lösung 1: Bootstrap-Script (empfohlen) + +Du schreibst dir ein Script wie: + +```bash +#!/bin/bash +set -e + +cd ~/dotfiles + +echo "→ Stowing configs" +stow hypr +stow waybar +stow zsh + +echo "→ Setting monitor config" +ln -sf desktop.conf hypr/.config/hypr/monitors/current.conf + +echo "→ Reloading Hyprland" +hyprctl reload +``` + +Dann einfach: + +```bash +./install.sh +``` + +💡 Das ist die professionellste Lösung. + +--- + +# 🔹 Lösung 2: Hostname-basierte Logik im Script + +```bash +HOST=$(hostname) + +if [[ "$HOST" == "desktop" ]]; then + ln -sf desktop.conf hypr/.config/hypr/monitors/current.conf +elif [[ "$HOST" == "laptop" ]]; then + ln -sf laptop.conf hypr/.config/hypr/monitors/current.conf +fi +``` + +Dann musst du nichts manuell wählen. + +--- + +# 🔹 Lösung 3: Makefile (sehr elegant) + +Beispiel: + +```make +install: + stow hypr + stow waybar + ./scripts/select-monitor.sh +``` + +Dann: + +```bash +make install +``` + +Sehr beliebt in Dotfile-Repos. + +--- + +# 🔹 Lösung 4: „echte“ Dotfile-Manager + +Wenn du wirklich Logik + Templates willst: + +* chezmoi +* yadm + +Diese können: + +* Hostname erkennen +* Variablen verwenden +* Templates generieren +* Skripte ausführen + +Aber sie sind komplexer als Stow. + +--- + +# 🎯 Empfehlung für dich (Hyprland + mehrere Systeme) + +Da du: + +* Monitor-Configs pro System brauchst +* wahrscheinlich Arch nutzt +* modular arbeiten willst + +👉 **Stow + Bootstrap-Script** ist die perfekte Balance. + +--- + +# 💬 Kurzantwort auf deine Frage + +| Frage | Antwort | +| ------------------------ | ----------------- | +| Führt Stow Skripte aus? | ❌ Nein | +| Kann man es kombinieren? | ✅ Ja | +| Beste Praxis? | Stow + install.sh | + +--- + diff --git a/Computerkram/Linux/Linux .desktop Dateien.md b/Computerkram/Linux/Linux .desktop Dateien.md new file mode 100644 index 0000000..fa40b80 --- /dev/null +++ b/Computerkram/Linux/Linux .desktop Dateien.md @@ -0,0 +1,23 @@ +Für Integration von Programmen ins Startmenü +Lege Datei `some_awesome_app.desktop` mit folgendem Inhalt: +```bash +[Desktop Entry] +Name=Name of Application +GenericName=Super generic Name +Comment=This is an awesome application +Exec=/path/to/executable +Icon=/path/to/icon +Type=Application +Terminal=false +Categories=Utility;Application; +``` + +- Für aktuellen Nutzer: `~/.local/share/applications` +- Systemweit (`sudo` beim Anlegen nicht vergessen): `/usr/share/applications` +## Weitere Felder +```bash +# ... +Encoding=UTF-8 +Version=1.0 +StartupWMClass=ExampleApp +``` diff --git a/Computerkram/Linux/Linux Drum Plugins.md b/Computerkram/Linux/Linux Drum Plugins.md new file mode 100644 index 0000000..7a634ff --- /dev/null +++ b/Computerkram/Linux/Linux Drum Plugins.md @@ -0,0 +1,29 @@ +Ich hab ein bisschen recherchiert und ein paar gute Optionen gefunden — sowohl Open Source / native [[Linux]]-PlugIns als auch Tipps, wie man bewährte Windows/Proprietär-Drum-Libraries unter Linux laufen lassen kann. Wenn du willst, kann ich auch ein paar kommerzielle Kandidaten heraussuchen, die unter Linux getestet sind. Hier zunächst ein Überblick: + +--- + +## 🎯 Native bzw. sehr gut unter Linux laufende Drum-Sampler / Drum-PlugIns + +Diese Tools/Plugins laufen nativ unter Linux / oder haben Linux-Versionen, und sind gute Alternativen oder Ergänzungen zu EZ-Drummer: + +| Plugin / Tool | Format / Linux-Support | Vorteile | Einschränkungen / Punkte, auf die man achten sollte | +| -------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **[[DrumGizmo]]** | VSTi & LV2 Version, stand-alone auch; multichannel, multilayered. | Sehr gute Drumsounds mit mehreren Velocity-Schichten; man kann einzelne Mikros / Kanäle nutzen, also gute Flexibilität beim Mischen. | Die Drums werden nicht immer sofort so fett wie bei kommerziellen Tools; erfordert gutes Setup (Routing, Mix) und ggf. eigene Kits. | +| **[[LinuxSampler]]** | VST, LV2, DSSI etc. | Sehr mächtig, kann große Sample-Libraries nutzen; volle Kontrolle. | Bedienung nicht so „slick“ wie bei Markenprodukten, evtl. Lernkurve; große Sample-Bibliotheken nötig für gute Vielfalt. | +| **[[drumkv1]]** | LV2 / Standalone (JACK / ALSA MIDI)-Client; native Linux. | Leichtgewichtig, einfach einzurichten; ideal wenn man nicht so viele Features braucht. | Kein High-End-Drumkit mit riesiger Bibliothek; klingt eher sauber/klassisch, nicht unbedingt super „produziert“. | +| **Geonkick** | Synthesizer Drum / Percussion; VST3 und LV2 auf Linux. | Sehr flexibel bei perkussiven Sounds, interessant wenn man eigene, eher synthetische Drums bauen will. | Eher auf Drum-Synthese fokussiert, nicht ein „Drumkit-Sammler“ mit kompletten Kits wie bei EZ Drummer etc. Kann sein, dass man noch eigene Samples oder Bearbeitung braucht, damit’s wirklich gut passt. | +| **Sitala** | Stand-alone / PlugIn Version, unterstützt Linux in früheren Versionen (V1) zumindest; sehr leicht zu bedienen. | Schnelle Ergebnisse; ideal für kreative Ideen, wenn man schnell Drums triggern möchte; UI ist simpel und effizient. | Wenn man ganz spezifische Kits oder sehr aufwendige Layer/Velocity braucht, stößt man evtl. an Grenzen; neuere Versionen evtl. eingeschränkter Linux-Support. | + +--- + +## 🔧 Kommerzielle PlugIns / Windows-Drum-Libraries unter Linux verwenden + +Wenn dir die Qualität / Klang von EZ-Drummer oder ähnlichen wichtig ist und du nicht komplett auf native Alternativen umsteigen willst, hier ein paar Tipps, wie man kommerzielle Plugins unter Linux zuverlässiger nutzen kann: + +- **Wine + VST Bridge / yabridge**: Viele Nutzer berichten, dass Windows-VSTs mit yabridge in Reaper unter Linux ziemlich gut laufen. Manche hatten Probleme mit Soundlibrary-Pfaden etc., aber wenn man das richtig einrichtet (z. B. Wineprefix, korrekter Pfad zu den Samples), dann klappt’s oft sehr gut. +- **Reaper Native + Linux-VST Unterstützung**: Die Linux-Version von Reaper kann native Linux VSTs nutzen, und mit yabridge auch Windows VSTs; das heißt, du kannst beides kombinieren. +- **Sample Libraries exportieren / konvertieren**: Wenn du z. B. Libraries hast, die in einem Format sind, das EZ-Drummer verwendet, könnte man prüfen, ob man die Samples in ein universelles Format bringt (z.B. SFZ) und dann mit einem Sampler wie LinuxSampler oder DrumGizmo nutzen. Das erspart Abhängigkeiten. + +--- + +Wenn du möchtest, kann ich ein paar **kommerziell verfügbare Drum-PlugIns** heraussuchen, die nachweislich unter Linux + Reaper stabil laufen, inkl. Preis & Klangbeispiele, damit du vergleichen kannst? Möchtest du das? \ No newline at end of file diff --git a/Computerkram/Linux/Linux Konsole Zeichen löschen.md b/Computerkram/Linux/Linux Konsole Zeichen löschen.md new file mode 100644 index 0000000..04416a2 --- /dev/null +++ b/Computerkram/Linux/Linux Konsole Zeichen löschen.md @@ -0,0 +1,32 @@ +Kann ich in einer [[Linux]] Konsole die komplette Eingabe auf einmal löschen? (z.B. wenn man sich beim Blättern durch die Historie oder beim Scuehn mit `STRG-R` "verrannt" hat)? + +--- +Ja, das geht 😊 – in der Linux-Shell (z. B. Bash, Zsh) kannst du mit **einem Shortcut die ganze Eingabezeile löschen**, ohne Zeichen für Zeichen löschen zu müssen: + +- **`Strg-u`** + Löscht den gesamten Text von der aktuellen Cursorposition bis zum Zeilenanfang. + Wenn der Cursor am Ende der Zeile steht (Standardfall), verschwindet die ganze Eingabe. + + +Weitere nützliche "Kill"-Shortcuts in der Bash/Zsh: + +- `Strg-k` → löscht von der Cursorposition bis zum Zeilenende + +- `Strg-w` → löscht das Wort links vom Cursor + +- `Strg-y` → fügt das zuletzt Gelöschte wieder ein (ähnlich "Paste") + + +Wenn du dich mit **`Strg-r` (Reverse Search)** "verrannt" hast: + +- Einfach **`Strg-g`** drücken → bricht die History-Suche ab und bringt dich zurück in eine leere Eingabezeile. + + +👉 Falls du wirklich _immer_ eine komplett neue, leere Zeile willst, ist die schnellste Kombination: + +- `Strg-u` (Cursor am Ende) oder + +- `Strg-g` (falls du gerade in einer History-Suche bist). + + +Willst du, dass ich dir eine kleine Übersicht als "Spickzettel" für Bash/Zsh-Shortcuts schreibe? \ No newline at end of file diff --git a/Computerkram/Linux/Linux Musikprogramme.md b/Computerkram/Linux/Linux Musikprogramme.md new file mode 100644 index 0000000..8cf2fcf --- /dev/null +++ b/Computerkram/Linux/Linux Musikprogramme.md @@ -0,0 +1,272 @@ + +Ich bin auf der Suche nach einer guten Software für meine MP3 Musiksammlung in Linux, mit die Synchronisation mit meinem Android Handy gut funktioniert. + +### Hintergrund +Bisher habe ich als Ex-Windows-Nutzer das Programm "Media-Monkey" in der Pro Version verwendet, d.h. auf dem PC und dem Handy mit der gleichnamigen App. + +### Anfrage +Bitte zeige mir gute Alternativen, bestehend aus Linux Programm für PC und Android App für Handy. + +### Anforderungen: +* Flexible Organisation der Library nach Benutzerdefinierten Kriterien (z.B. Album Artist, Genre, Album, etc.) +* Bearbeitungsmöglichkeiten aller Song Infos +* Bewertungssystem und Verschlagwortung +* Playlisten: statisch und dynamsisch (d.h. regelbasiert) +* Leichte Synchronisierbarkeit zwischen Rechner und Handy: + * Änderungen an Metadaten, insbes. "Last Played" werden in beide Richtungen übernommen + * Möglichkeit die Bitrate der MP3s beim Synchronisieren anzupassen (z.B. um Speicherplatz auf Handy zu sparen) + * Synchronisation kabelgebunden oder über WLAN + +### Optionale Anforderungen +* Möglichkeit, fehlende Metadaten aus WWW zu ergänzen +* Erstellung von Benutzerdefinierten Metadaten Feldern, z.B. als Berechnung aus anderen Feldern +--- + +--- +Super, danke für die präzise Beschreibung – das hilft sehr! +Ich fasse mal die Landschaft für dich zusammen: es gibt unter Linux kein exaktes 1:1-Pendant zu **MediaMonkey**, aber einige Kombinationen aus Desktop-Software + Android-App können sehr nahe herankommen. + +--- + +## 1. **MusicBee (via Wine) + Gonemad / PowerAmp (Android)** + +- **Linux (Wine):** MusicBee läuft recht stabil unter Wine. Viele Ex-MediaMonkey-User nutzen es als Ersatz, weil es die meisten Features (flexible Library, Tags, Bewertungen, Smart-Playlists, Metadaten aus dem Netz) abdeckt. + +- **Android:** Keine eigene App, aber Sync mit **GoneMAD** oder **PowerAmp** möglich. Mit Tools wie `syncthing` oder `Resilio Sync` kannst du Library, Ratings & Playcounts abgleichen. + +- **Pro:** Funktionsumfang fast wie MediaMonkey. + +- **Contra:** Keine native Linux-App, Integration Handy↔PC muss manuell über Sync-Tools eingerichtet werden. + + +--- + +## 2. **Clementine / Strawberry (Linux) + Android App Clementine Remote / DSub** + +- **Linux:** [[Strawberry 1]] ist ein Fork von Clementine, moderner gepflegt. + + - Bibliotheksorganisation nach vielen Kriterien. + + - Metadatenbearbeitung, inkl. Coverdownload von Last.fm, MusicBrainz. + + - Playlists: statisch + dynamisch. + +- **Android:** Offizielle Clementine-Remote-App für Steuerung, oder Streaming via Subsonic-kompatibler Apps (z. B. [[DSub]], [[Ultrasonic]]). + - siehe auch [[Subsonic-API]] + +- **Sync:** + + - Metadaten (Playcount, Ratings) werden am PC gespeichert. + + - Handy-Sync ist etwas frickelig, echte **bidirektionale Playcount-Synchronisation** gibt es nicht nativ. + +- **Pro:** Native Linux-App, offene Formate. + +- **Contra:** Sync mit Handy nicht so nahtlos wie MediaMonkey. + + +--- + +## 3. **Amarok / Elisa (KDE) + Android (KDE Connect, VLC, PowerAmp)** + +- **Linux:** Amarok war früher sehr stark, inzwischen etwas veraltet. Elisa ist der moderne KDE-Player, aber weniger mächtig in Smart-Playlists. + +- **Android:** Mit **KDE Connect** kannst du Dateien kabellos synchronisieren, aber Metadaten-Sync (z. B. "Last Played") fehlt. + +- **Pro:** Schön in KDE integriert. + +- **Contra:** Nicht so mächtig wie MediaMonkey. + + +--- + +## 4. **Rhythmbox + Android (Lollypop / VLC)** + +- **Linux:** Rhythmbox (GNOME Standard) oder Lollypop (modernere Oberfläche). + +- **Features:** Library, Metadaten, Bewertungen. + +- **Sync:** Per Kabel (MTP) oder WLAN/Sync-Tools, aber kein sauberer Playcount-Abgleich. + +- **Contra:** Sehr basic, keine regelbasierten Playlists wie MediaMonkey. + + +--- + +## 5. **Self-Hosted Server + Android (Subsonic/Airsonic + DSub/Ampache)** + +- **Linux:** Airsonic, [Navidrome] oder Koel als **Musikserver**. + +- **Features:** Vollständige Weboberfläche, flexible Library, Tags, Playcounts, Bewertungen. + +- **Android:** Mit Apps wie **DSub**, **Substreamer**, **Ultrasonic** Zugriff und **automatische Playcount-Sync**. + +- **Pro:** + + - Playcounts, Metadaten und Playlists sind _immer synchronisiert_. + + - Zugriff auch von unterwegs. + +- **Contra:** Kein klassischer "Desktop-Player", sondern Server-Setup. Eher für Power-User. + + +--- + +## 6. **Syncthing / rsync als Backend für bestehende Player** + +- Falls dir wichtig ist, die MP3s in voller Struktur 1:1 zwischen Rechner und Handy zu haben (inkl. Playcounts, Bitrate-Anpassung), kannst du auch einen reinen Player wie **Strawberry** am PC + **GoneMAD** oder **PowerAmp** am Handy nutzen, und den Abgleich über **Syncthing** erledigen. + +- Bitraten-Transkodierung beim Sync ist tricky: am besten über ein Script oder mit Tools wie **FFmpeg** beim Kopieren lösen. + + +--- + +## Fazit (Empfehlungen) + +- **"Am nächsten an MediaMonkey"** → **MusicBee unter Wine + GoneMAD/PowerAmp auf Android** (aber kein native Linux). + +- **Native Linux-Lösung, solide & gepflegt** → **Strawberry auf Linux + GoneMAD auf Android**, Sync per Syncthing/rsync. + +- **Wenn Playcount/Rating-Sync über Geräte _wirklich_ zentral ist** → **[[Navidrome]] (Server) + DSub/Ultrasonic auf Android**. + + +--- + +👉 Frage an dich: +Ist dir wichtiger, dass das Ganze **nativ auf Linux läuft** (also Wine vermeiden), oder dass du **möglichst nahe an der MediaMonkey-Experience bleibst**, auch wenn’s Wine erfordert? + +--- +Ich ziehe es vor, wenn es nativ unter Linux läuft. Es **muss** nicht auch nicht Media Monkey nachahmen, es sollte vom Funktionsumfang nur ähnlich mächtig sein. Wenn für Synchronisation extra Tools benötigt werden ist das ok. Wichtig wäre mir, dass Bearbeitungen am PC (Hinzugefügte Songs, Playlisten statisch und dynamisch, Metadaten etc) möglichst 1 zu 1 auch auf dem Handy verfügbar sind. + +--- +Perfekt — danke für die Präzisierung. Du willst also **native Linux**-Werkzeuge, die in Summe ungefähr so mächtig sind wie MediaMonkey, und die Änderungen am PC (neue Songs, statische + dynamische Playlists, Metadaten usw.) sollen **möglichst 1:1 auf dem Android-Handy verfügbar** sein. Ich habe zwei praxiserprobte, native-unter-Linux-Workflows für genau dieses Ziel — einer ist _server-zentriert_ (am zuverlässigsten für Bidirektionalität von Playcounts/Playlists/Metadaten), der andere ist _Datei-Sync/Offline_-orientiert (besser für rein lokale Dateien/Offline-Nutzung, aber mit Einschränkungen bei Playcount/Ratings). Ich liste jeweils Voraussetzungen, wie es funktioniert, Vor-/Nachteile und konkrete Umsetzungspunkte. + +# Empfehlung A — **(Meine Top-Wahl)** Lokaler Musik-Server ([[Navidrome]]/Airsonic) + native Player (Strawberry) auf PC + Subsonic-Client auf Android (z. B. DSub / Ultrasonic) + +**Warum:** [[Navidrome]] (leichtgewichtiger, moderner Subsonic-kompatibler Server) läuft nativ unter Linux, indexiert deine Musikdateien und stellt Bibliothek + Playlists + Playcounts + Ratings zentral zur Verfügung. Android-Clients, die das Subsonic-API unterstützen, können sowohl streamen als auch offline cachen und melden Wiedergaben/Playcounts zurück an den Server — dadurch hast du eine echte 1:1-Synchronisation der Nutzungsdaten zwischen PC und Handy. [Navidrome] bietet außerdem Transcoding/Download-Transkodierung (nützlich, um Bitrate beim Übertragen zu reduzieren). Auf dem Desktop nutzt du einen richtigen Player/Tag-Editor wie **Strawberry** zum Bearbeiten der Dateien; der Server erkennt Änderungen bei Rescan/Auto-Import. ([[Navidrome]](https://www.Navidrome.org/docs/overview/?utm_source=chatgpt.com "[[Navidrome]] Overview")) + +Wie das zusammenwirkt — Kurzablauf: + +1. Auf dem Linux-PC: music-folder (z. B. `~/Music`) → Strawberry zum Abspielen & Tag-Editing. Strawberry ist native, hat Smart/Dynamic-Playlists und Tag-Editoren. ([strawberrymusicplayer.org](https://www.strawberrymusicplayer.org/?utm_source=chatgpt.com "Strawberry Music Player")) + +2. Auf dem Linux-PC: [[Navidrome]] (als Dienst oder Docker) so konfigurieren, dass es auf genau denselben Music-Ordner zeigt. [[Navidrome]] indexiert die Dateien, liest Tags, Playlists (importiert `.m3u`) und verwaltet Playcounts/ratings serverseitig. ([[Navidrome]](https://www.Navidrome.org/docs/overview/?utm_source=chatgpt.com "[[Navidrome]] Overview")) + +3. Auf Android: Subsonic-kompatible App installieren (z. B. **DSub**, **Ultrasonic** oder Subsonic-App). Diese Apps können streamen, offline cachen/downloaden und (je nach App/Server-Einstellung) Playbacks/Playcounts an [[Navidrome]] zurückmelden; sie unterstützen auch clientseitiges Transcoding / Download-Qualitätssteuerung. (Subsonic-App-Ökosystem ist groß, DSub ist ein verbreiteter Client.) ([subsonic.org](https://www.subsonic.org/pages/apps.jsp?utm_source=chatgpt.com "Subsonic Apps")) + + +Wesentliche Vorteile: + +- **Echte Bidirektionalität** für Playcount/Play/Rating, wenn Client ↔ Server dies unterstützt (sehr viel zuverlässiger als reine Datei-Syncs). ([[Navidrome]](https://www.Navidrome.org/docs/overview/?utm_source=chatgpt.com "[[Navidrome]] Overview")) + +- **On-the-fly Transcoding / Bitrate-Limit** beim Stream/Download — du kannst z. B. mobil immer in 128–192 kbps laden, während der PC die Originals behält. ([[Navidrome]](https://www.Navidrome.org/docs/usage/configuration-options/?utm_source=chatgpt.com "[[Navidrome]] Configuration Options")) + +- Desktop bleibt native (Strawberry), Server läuft nativ unter Linux. ([strawberrymusicplayer.org](https://www.strawberrymusicplayer.org/?utm_source=chatgpt.com "Strawberry Music Player")) + + +Nachteile / Dinge, die du beachten solltest: + +- Es ist kein „klassischer“ Einzelprogramm-Desktop-Workflow mehr, sondern ein **Server + Clients**-Setup (läuft aber lokal auf deinem Rechner, keine Cloud nötig). + +- Manche Subsonic-Clients handhaben Offline-Caching unterschiedlich (Ordnerstruktur, Caching-Verhalten). Testen lohnt sich. ([GitHub](https://github.com/airsonic-advanced/airsonic-advanced/issues/873?utm_source=chatgpt.com "DSub sync/cache with Airsonic 11 dumps all files into main ...")) + + +**Kurz-Setup-Hinweise:** + +- Installiere [[Navidrome]] (Deb/Flatpak/Docker) und stelle `MUSIC_FOLDER` auf deinen bestehenden Musikordner. Aktiviere ggf. `AutoImportPlaylists`. ([[Navidrome]](https://www.Navidrome.org/docs/usage/configuration-options/?utm_source=chatgpt.com "[[Navidrome]] Configuration Options")) + +- Installiere Strawberry als Desktop-Player und bearbeite Tags/Playlists dort; [[Navidrome]] neu scannen lassen oder Auto-Rescan aktivieren. ([strawberrymusicplayer.org](https://www.strawberrymusicplayer.org/?utm_source=chatgpt.com "Strawberry Music Player")) + +- Auf Android: DSub/Ultrasonic konfigurieren (Server-URL mit deiner lokalen IP), in der App die Download/Transcode-Qualität setzen. ([subsonic.org](https://www.subsonic.org/pages/apps.jsp?utm_source=chatgpt.com "Subsonic Apps")) + + +--- + +# Empfehlung B — **Datei-Sync (offline) Workflow**: Strawberry (Linux) + Syncthing (oder rsync) + Android-Player (GoneMAD / Poweramp) + +**Warum:** Wenn du viel offline hörst und tatsächliche Dateien auf dem Handy brauchst (z. B. Hi-Res oder bestimmte Ordnerstruktur), ist Syncthing eine sehr komfortable, native Lösung zum Spiegeln von Ordnern PC ↔ Handy. Strawberry bearbeitet Tags/Playlists auf dem PC und die Dateien werden 1:1 auf's Handy kopiert. ([strawberrymusicplayer.org](https://www.strawberrymusicplayer.org/?utm_source=chatgpt.com "Strawberry Music Player")) + +Wie das zusammenwirkt — Kurzablauf: + +1. Strawberry verwaltet die Dateien lokal und erzeugt Playlists (M3U). + +2. Syncthing synchronisiert den Music-Ordner (und Playlist-Exports) automatisch auf das Handy. Syncthing läuft nativ unter Linux und Android. ([Gist](https://gist.github.com/johanwiden/d14ec414bd212e2ee8c2fae576115ef7?utm_source=chatgpt.com "How to configure Syncthing for Android")) + +3. Auf Android: ein mächtiger Offline-Player wie **GoneMAD** oder **Poweramp** liest die Dateien/Playlists vom synchronisierten Ordner. + + +Vorteile: + +- Volle Offline-Verfügbarkeit (keine Server-Software nötig). + +- Absolute Dateiintegrität — exakt die gleichen MP3/FLAC liegen auf beiden Geräten. + + +Wesentliche Einschränkungen (sehr wichtig): + +- **Playcounts / Ratings**: Viele Android-Player (z. B. Poweramp) speichern Playcounts/Rating in einer **internen App-Datenbank** und schreiben diese **nicht** zuverlässig zurück in die MP3-Tags (POPM/PCNT). Dadurch geht die echte bidirektionale Synchronisation von „Last played / playcount / rating“ verloren, bzw. sie ist nur mit zusätzlichen Tools/Workarounds möglich. Poweramp z.B. unterstützt POPM nicht als schreibbaren Standard-Rating-Export. GoneMAD hat einige Optionen, kann aber nicht immer sauber bidirektional zu jedem Desktop-Tool synchronisieren. ([Poweramp](https://forum.powerampapp.com/topic/21099-will-not-recognize-ratings-tags/?utm_source=chatgpt.com "Will not recognize ratings tags - Poweramp Feature Requests")) + +- Android-Medienindexer kann neue Dateien verzögert erkennen; manchmal muss man den Index anstoßen oder die App neu starten, wenn Syncthing neue Musik ablegt. ([Syncthing Community Forum](https://forum.syncthing.net/t/music-synced-onto-phone-not-picked-up-by-android/22191?utm_source=chatgpt.com "Music Synced onto Phone Not Picked Up by Android")) + + +Workarounds: + +- Verwende ID3-Frames, die als Standard existieren — z. B. **PCNT** (Play Counter) oder **POPM** (Popularimeter) — und scripte gelegentlich ein Update/Export/Import dieser Frames zwischen Player-DB und Dateien. Die PCNT-Frame ist Teil der ID3-Spec und kann playcount direkt in die Datei schreiben — das funktioniert aber nur, wenn der Android-Player diese Frames auch schreibt/liest. ([id3.org](https://id3.org/id3v2.3.0?utm_source=chatgpt.com "id3v2.3.0")) + +- Manche Nutzer verwenden periodische Exporte (z. B. M3U/CSV) und ein kleines Script, das die DB-Werte abgleicht — ist aber Aufwand und fragile Lösung. (Wenn du experimentierfreudig bist, möglich.) + + +--- + +# Vergleich & Entscheidungshilfe — kurz + +- **Wenn du wirklich möchtest, dass Playcounts / LastPlayed / Ratings verlässlich zwischen PC ↔ Handy synchron sind → wähle den Server-Ansatz ([[Navidrome]] / Airsonic)**. Das ist die sauberste, wartungsarme Lösung für bidirektionale Nutzungsdaten; zusätzlich hast du komfortable Transcoding-Optionen für mobile Daten/Storage. ([[Navidrome]](https://www.Navidrome.org/docs/overview/?utm_source=chatgpt.com "[[Navidrome]] Overview")) + +- **Wenn du maximale Offline-Kontrolle über die Dateien willst (keine Serverstruktur) → wähle Syncthing + ein mächtiges Android-Player,** akzeptiere aber Einschränkungen bei Ratings/Playcounts bzw. plane zusätzliche Scripts/Workarounds ein. ([Gist](https://gist.github.com/johanwiden/d14ec414bd212e2ee8c2fae576115ef7?utm_source=chatgpt.com "How to configure Syncthing for Android")) + + +--- + +# Konkrete Vorschläge zum sofortigen Ausprobieren (in dieser Reihenfolge) + +1. **Testlauf Server-Option (empfohlen):** + + - Installiere [[Navidrome]] (Docker oder Paket) und zeige es auf `~/Music`. ([[Navidrome]] ist leicht, kann lokal laufen.) ([[Navidrome]](https://www.Navidrome.org/docs/overview/?utm_source=chatgpt.com "[[Navidrome]] Overview")) + + - Installiere DSub (oder Ultrasonic) auf dem Handy, verbinde mit [[Navidrome]]. Teste Streaming + Offline-Download + setzte Download-Bitrate auf z. B. 160 kbps. ([subsonic.org](https://www.subsonic.org/pages/apps.jsp?utm_source=chatgpt.com "Subsonic Apps")) + + - Auf dem PC: installiere **Strawberry**, bearbeite ein paar Tags & Playlists, lasse [[Navidrome]] neu scannen — prüfe die Änderungen im Android-Client. ([strawberrymusicplayer.org](https://www.strawberrymusicplayer.org/?utm_source=chatgpt.com "Strawberry Music Player")) + +2. **Falls du stattdessen Offline-Dateien bevorzugst:** + + - Installiere **Syncthing** auf PC + Android, sync einen kleinen Test-Musikordner. ([Gist](https://gist.github.com/johanwiden/d14ec414bd212e2ee8c2fae576115ef7?utm_source=chatgpt.com "How to configure Syncthing for Android")) + + - Auf Android: teste **GoneMAD** (sehr anpassbar) oder **Poweramp** als Player, probiere, ob Ratings/Playcounts in deiner Kombination zuverlässig geschrieben/gezogen werden (Hinweis: Poweramp schreibt POPM nicht). ([Google Play](https://play.google.com/store/apps/details?hl=en_US&id=gonemad.gmmp&utm_source=chatgpt.com "GoneMAD Music Player - Apps on Google Play")) + + +--- + +# Quellen (wichtigste Belege) + +- Strawberry — native Linux Player: Smart/dynamic playlists, Tag-Editor, MusicBrainz/cover lookup. ([strawberrymusicplayer.org](https://www.strawberrymusicplayer.org/?utm_source=chatgpt.com "Strawberry Music Player")) + +- [[Navidrome]] — leichter Subsonic-kompatibler Server, lokal nutzbar; Optionen für AutoImportPlaylists / Transcoding/Download-Transcode. ([[Navidrome]](https://www.Navidrome.org/docs/overview/?utm_source=chatgpt.com "[[Navidrome]] Overview")) + +- Subsonic/DSub ecosystem — Android-Clients für Subsonic/[[Navidrome]] (Streaming, Offline Caching, Bitrate/Transcode Optionen). ([subsonic.org](https://www.subsonic.org/pages/apps.jsp?utm_source=chatgpt.com "Subsonic Apps")) + +- ID3-Frames (PCNT / POPM) — Playcount-Frame `PCNT` ist Teil der ID3v2-Spec (kann in Datei gespeichert werden). ([id3.org](https://id3.org/id3v2.3.0?utm_source=chatgpt.com "id3v2.3.0")) + +- Poweramp & Rating/Tagging Limit: Poweramp schreibt/liest POPM/PCNT nicht standardmäßig; Ratings werden intern gespeichert — wichtige Einschränkung für Datei-Sync Workflows. ([Poweramp](https://forum.powerampapp.com/topic/21099-will-not-recognize-ratings-tags/?utm_source=chatgpt.com "Will not recognize ratings tags - Poweramp Feature Requests")) + +- Syncthing für Datei-Sync Android ↔ PC — verbreitete Praxis, aber Android-Indexing / Rechte / folder ownership sind zu beachten. ([Gist](https://gist.github.com/johanwiden/d14ec414bd212e2ee8c2fae576115ef7?utm_source=chatgpt.com "How to configure Syncthing for Android")) + + +--- + +Wenn du willst, mache ich sofort eines von beiden für dich praktisch: + +- **Variante A:** Ich erstelle dir eine Schritt-für-Schritt-Anleitung (konkret für Debian/Ubuntu/Fedora) zum Installieren/Einrichten von [[Navidrome]] + Strawberry + DSub (inkl. Beispiel-Config für Transcoding/AutoImport). + +- **Variante B:** Oder ich schreibe ein kurzes Syncthing-Setup-Tutorial + Hinweise, wie du Ratings/Playcounts am besten per ID3/Script synchronisierst (inkl. Beispielscript, das `PCNT`/`POPM` per `mutagen` oder `eyeD3` setzt). + + +Sag mir einfach welches Setup du zuerst ausprobieren willst — ich liefere die konkrete, sofort ausführbare Anleitung (inkl. Konfig-Snippets). \ No newline at end of file diff --git a/Computerkram/Linux/Linux Terminal Shortcut.md b/Computerkram/Linux/Linux Terminal Shortcut.md new file mode 100644 index 0000000..4976336 --- /dev/null +++ b/Computerkram/Linux/Linux Terminal Shortcut.md @@ -0,0 +1,34 @@ +Is there a keyboard shortcut on linux to open a terminal + +--- +Yes 👍 — most Linux desktop environments (DEs) have a default keyboard shortcut for opening a terminal, but it can vary depending on which one you’re using: + +- **GNOME (Ubuntu, Fedora, Debian, etc.):** + `Ctrl + Alt + T` + +- **KDE Plasma (Kubuntu, openSUSE, etc.):** + Usually also `Ctrl + Alt + T` (but can be customized). + +- **XFCE (Xubuntu, etc.):** + Often `Ctrl + Alt + T`, or you can set your own in _Settings → Keyboard → Application Shortcuts_. + +- **Others (MATE, Cinnamon, LXQt, etc.):** + Many also use `Ctrl + Alt + T` by default. + + +If it doesn’t work, you can always **assign your own shortcut**: + +1. Go to your system’s **Keyboard Settings**. + +2. Find **Custom Shortcuts** (or _Keyboard Shortcuts_). + +3. Add a new one: + + - Command: `gnome-terminal` (or `konsole`, `xfce4-terminal`, depending on your DE). + + - Shortcut: choose something like `Ctrl + Alt + T`. + + +--- + +👉 Which desktop environment or Linux distro are you using? I can give you the exact steps for your setup. \ No newline at end of file diff --git a/Computerkram/Linux/Linux.md b/Computerkram/Linux/Linux.md new file mode 100644 index 0000000..ba2c658 --- /dev/null +++ b/Computerkram/Linux/Linux.md @@ -0,0 +1,15 @@ +[[Linux Musikprogramme]] +[[Softlinks 1]] +[[Synchronisation & Backup 1]] + +# Konsolen Know-How +[[Linux Konsole Zeichen löschen]] +[[Paketinstallation aus tar.gz]] +[[Disable KVM for VirtualBox]] +[[Linux Terminal Shortcut]] +[[Drives & Mounts 1]] +[[Computerkram/find]] +[[Link-Verknüpfung in Linux]] + + + diff --git a/Computerkram/Linux/Meine Config.md b/Computerkram/Linux/Meine Config.md new file mode 100644 index 0000000..7b06901 --- /dev/null +++ b/Computerkram/Linux/Meine Config.md @@ -0,0 +1,3 @@ +* [[ssh Key erstellen]] +* [[mein fstab]] +* \ No newline at end of file diff --git a/Computerkram/Linux/Navidrome mit Strawberry.md b/Computerkram/Linux/Navidrome mit Strawberry.md new file mode 100644 index 0000000..5dbfc17 --- /dev/null +++ b/Computerkram/Linux/Navidrome mit Strawberry.md @@ -0,0 +1,142 @@ + + + + +**Warum:** [[Navidrome]] (leichtgewichtiger, moderner Subsonic-kompatibler Server, -> [[Subsonic-API]]) läuft nativ unter Linux, indexiert deine Musikdateien und stellt Bibliothek + Playlists + Playcounts + Ratings zentral zur Verfügung. Android-Clients, die das Subsonic-API unterstützen, können sowohl streamen als auch offline cachen und melden Wiedergaben/Playcounts zurück an den Server — dadurch hast du eine echte 1:1-Synchronisation der Nutzungsdaten zwischen PC und Handy. [Navidrome] bietet außerdem Transcoding/Download-Transkodierung (nützlich, um Bitrate beim Übertragen zu reduzieren). Auf dem Desktop nutzt du einen richtigen Player/Tag-Editor wie [[Strawberry 1]] zum Bearbeiten der Dateien; der Server erkennt Änderungen bei Rescan/Auto-Import. ([[Navidrome]](https://www.Navidrome.org/docs/overview/?utm_source=chatgpt.com "[[Navidrome]] Overview")) + +Wie das zusammenwirkt — Kurzablauf: + +1. Auf dem Linux-PC: music-folder (z. B. `~/Music`) → Strawberry zum Abspielen & Tag-Editing. Strawberry ist native, hat Smart/Dynamic-Playlists und Tag-Editoren. ([strawberrymusicplayer.org](https://www.strawberrymusicplayer.org/?utm_source=chatgpt.com "Strawberry Music Player")) + +2. Auf dem Linux-PC: [[Navidrome]] (als Dienst oder Docker) so konfigurieren, dass es auf genau denselben Music-Ordner zeigt. [[Navidrome]] indexiert die Dateien, liest Tags, Playlists (importiert `.m3u`) und verwaltet Playcounts/ratings serverseitig. ([[Navidrome]](https://www.Navidrome.org/docs/overview/?utm_source=chatgpt.com "[[Navidrome]] Overview")) + +3. Auf Android: Subsonic-kompatible App installieren (z. B. **DSub**, **Ultrasonic** oder Subsonic-App). Diese Apps können streamen, offline cachen/downloaden und (je nach App/Server-Einstellung) Playbacks/Playcounts an [[Navidrome]] zurückmelden; sie unterstützen auch clientseitiges Transcoding / Download-Qualitätssteuerung. (Subsonic-App-Ökosystem ist groß, DSub ist ein verbreiteter Client.) ([subsonic.org](https://www.subsonic.org/pages/apps.jsp?utm_source=chatgpt.com "Subsonic Apps")) + + +Wesentliche Vorteile: + +- **Echte Bidirektionalität** für Playcount/Play/Rating, wenn Client ↔ Server dies unterstützt (sehr viel zuverlässiger als reine Datei-Syncs). ([[Navidrome]](https://www.Navidrome.org/docs/overview/?utm_source=chatgpt.com "[[Navidrome]] Overview")) + +- **On-the-fly Transcoding / Bitrate-Limit** beim Stream/Download — du kannst z. B. mobil immer in 128–192 kbps laden, während der PC die Originals behält. ([[Navidrome]](https://www.Navidrome.org/docs/usage/configuration-options/?utm_source=chatgpt.com "[[Navidrome]] Configuration Options")) + +- Desktop bleibt native (Strawberry), Server läuft nativ unter Linux. ([strawberrymusicplayer.org](https://www.strawberrymusicplayer.org/?utm_source=chatgpt.com "Strawberry Music Player")) + + +Nachteile / Dinge, die du beachten solltest: + +- Es ist kein „klassischer“ Einzelprogramm-Desktop-Workflow mehr, sondern ein **Server + Clients**-Setup (läuft aber lokal auf deinem Rechner, keine Cloud nötig). + +- Manche Subsonic-Clients handhaben Offline-Caching unterschiedlich (Ordnerstruktur, Caching-Verhalten). Testen lohnt sich. ([GitHub](https://github.com/airsonic-advanced/airsonic-advanced/issues/873?utm_source=chatgpt.com "DSub sync/cache with Airsonic 11 dumps all files into main ...")) + + +**Kurz-Setup-Hinweise:** + +- Installiere [[Navidrome]] (Deb/Flatpak/Docker) und stelle `MUSIC_FOLDER` auf deinen bestehenden Musikordner. Aktiviere ggf. `AutoImportPlaylists`. ([[Navidrome]](https://www.Navidrome.org/docs/usage/configuration-options/?utm_source=chatgpt.com "[[Navidrome]] Configuration Options")) + +- Installiere Strawberry als Desktop-Player und bearbeite Tags/Playlists dort; [[Navidrome]] neu scannen lassen oder Auto-Rescan aktivieren. ([strawberrymusicplayer.org](https://www.strawberrymusicplayer.org/?utm_source=chatgpt.com "Strawberry Music Player")) + +- Auf Android: DSub/Ultrasonic konfigurieren (Server-URL mit deiner lokalen IP), in der App die Download/Transcode-Qualität setzen. ([subsonic.org](https://www.subsonic.org/pages/apps.jsp?utm_source=chatgpt.com "Subsonic Apps")) + + +--- + +### 1. **Playcounts / Metadaten in Strawberry vs. Navidrome** + +- **Wenn du Strawberry „lokal“ (eigene Library, also direkt auf den Musikdateien im Dateisystem) benutzt:** + + - Playcounts und Ratings werden **nur in Strawberries interner Datenbank** gepflegt, nicht in Navidrome. + + - Metadatenänderungen (Tags, Cover etc.), die du in den Dateien speicherst, **sieht Navidrome** beim nächsten Scan (manuell oder automatisch). → Cover/Tags sind also synchron, **aber Playcounts und Ratings nicht**. + +- **Wenn du Strawberry „über Streaming“ mit Navidrome verbindest:** + + - Playcounts und Ratings werden im **Navidrome-Server** gespeichert, d.h. Handy + PC greifen auf denselben Zähler/Rating zurück. + + - Änderungen in der Datei selbst sind dann nachrangig (es sei denn, du editierst die Tags explizit im Dateisystem). + + +👉 Empfehlung: + +- Für **Playcounts und Bewertungen**, immer über das Navidrome-Streaming-Backend hören. + +- Für **Tag-Bearbeitung** (Album Artist, Genre, Cover etc.) kannst du ruhig Strawberry lokal verwenden → nach dem Speichern erkennt Navidrome die geänderten Tags. + + +--- + +### 2. **Navidrome auf Synology NAS installieren – sinnvoll?** + +- **Ja, absolut sinnvoll.** Vorteile: + + - Deine Musik liegt vermutlich sowieso schon auf der NAS. + + - Navidrome kann 24/7 laufen, unabhängig vom PC. + + - Dein Handy kann direkt auf die NAS zugreifen (auch unterwegs, wenn du Portfreigabe oder VPN einrichtest). + +- Installationsmöglichkeiten: + + - **Docker-Container** (empfohlen, wenn du Docker auf der Synology nutzt). Das offizielle Image ist `deluan/navidrome`. + + - Oder als native Binary in einer Synology-Chroot/Entwicklungsumgebung (Docker ist aber deutlich einfacher). + + +👉 Empfehlung: Wenn die NAS immer läuft → installiere Navidrome dort. Dann kannst du Strawberry am PC so konfigurieren, dass er sich nur noch als Client auf den NAS-Server verbindet. + +--- + +### 3. **Navidrome beim Systemstart automatisch starten lassen** + +Hängt davon ab, wie du es installiert hast: + +- **Systemd-Service (klassisch, wenn du es auf deinem Linux-PC laufen lässt):** + + 1. Service-Datei erstellen: + + ```ini + # /etc/systemd/system/navidrome.service + [Unit] + Description=Navidrome Music Server + After=network.target + + [Service] + User=deinuser + Group=deinuser + ExecStart=/usr/local/bin/navidrome --configfile /etc/navidrome.toml + Restart=on-failure + WorkingDirectory=/home/deinuser + + [Install] + WantedBy=multi-user.target + ``` + + 2. Aktivieren & starten: + + ```bash + sudo systemctl enable navidrome + sudo systemctl start navidrome + ``` + +- **Docker + Systemd:** + Wenn du Navidrome via Docker laufen lässt, kannst du entweder `docker run --restart=always ...` nutzen oder einen systemd-Service schreiben, der den Container startet. + +- **Synology NAS (Docker):** + Die Synology Docker-Oberfläche bietet eine Einstellung **„Automatisch starten“** beim Container an. Einfach anhaken, dann startet Navidrome mit der NAS. + + +--- + +✅ **Kurz zusammengefasst:** + +- **Playcounts/Ratings:** Nur über Navidrome-Streaming → sonst bleiben sie lokal in Strawberry. + +- **Metadaten (Tags, Cover):** Bearbeitung in Strawberry → Navidrome liest sie beim nächsten Scan ein. + +- **NAS:** Ideal für Dauerbetrieb, am besten per Docker. + +- **Autostart:** systemd-Service (Linux) oder Autostart in Synology Docker aktivieren. + + +--- + +👉 Soll ich dir eine konkrete Schritt-für-Schritt-Anleitung für **Navidrome auf Synology NAS (per Docker)** schreiben, inkl. `docker run`-Beispiel und Volume-Mounts (z. B. für `music/` und `data/`)? Dann kannst du deine PC-Instanz ablösen und alles zentralisieren. diff --git a/Computerkram/Linux/Navidrome.md b/Computerkram/Linux/Navidrome.md new file mode 100644 index 0000000..dc88aa6 --- /dev/null +++ b/Computerkram/Linux/Navidrome.md @@ -0,0 +1,97 @@ + + +Hier eine ausführliche Vorstellung von **Navidrome**: + +--- + +## 🔎 Was ist Navidrome? + +Navidrome ist ein **selbstgehosteter Musikserver** für \[\[Linux\]\] (und andere Plattformen). Er funktioniert ähnlich wie Spotify oder Apple Music – nur mit deiner eigenen Musikbibliothek. Du lädst deine Audiodateien (MP3, FLAC, OGG, AAC etc.) auf deinen Server, und Navidrome macht sie über ein Web-Interface oder kompatible Apps (\[\[Subsonic-API\]\]) überall verfügbar. + +Kurz: +👉 Deine Musik, dein Server, jederzeit und überall streambar. + +--- + +## 🎶 Was kann Navidrome? + +- **Streaming im Browser** mit einem modernen, responsiven Webplayer. +- **Unterstützt viele Clients** über die Subsonic-API (z. B. \[\[DSub\]\], \[\[Ultrasonic\]\], \[\[Substreamer\]\], Symfonium, etc.). +- **Automatische Bibliotheksindizierung**: Scannt Ordner, liest Metadaten und baut deine Mediathek. +- **Benutzerverwaltung**: Mehrere Accounts mit eigenen Playlists, Favoriten und Rechten. +- **Playlists & Favoriten** (inkl. Smart-Playlists). +- **Transcoding on the fly**: Wandelt Dateien in kleinere Formate um, falls deine Verbindung langsam ist. +- **Leichtgewichtig & ressourcenschonend** (geschrieben in Go). +- **Cross-Plattform**: \[\[Linux\]\], Windows, macOS, ARM (z. B. Raspberry Pi). +- **Docker-Images verfügbar** für einfache Installation. + +--- + +## ✅ Vorteile gegenüber anderen Lösungen + +- **Leichtgewichtiger als Plex oder Jellyfin**, weil es sich auf Musik konzentriert. +- **Moderner und aktiver entwickelt als Airsonic, Subsonic & Co.** +- **Einfach zu installieren und zu warten** (ein Binary oder Docker-Container reicht). +- **Sehr niedrige Hardware-Anforderungen** – läuft problemlos auf kleinen VPS oder einem Raspberry Pi. +- **Sehr gute Client-Kompatibilität** durch \[\[Subsonic-API\]\]. + +--- + +## 🛠️ Installation unter Linux + +### Variante 1: Per Binary (klassisch) + +1. Lade die aktuelle Version herunter: + + ```bash + wget https://github.com/navidrome/navidrome/releases/latest/download/navidrome_linux_amd64.tar.gz + tar xzf navidrome_linux_amd64.tar.gz + sudo mv navidrome /usr/local/bin/ + ``` +2. Erstelle einen Benutzer für Navidrome: + + ```bash + sudo useradd -r -s /bin/false navidrome + ``` +3. Erstelle ein Konfigurationsverzeichnis: + + ```bash + sudo mkdir /var/lib/navidrome + sudo chown navidrome:navidrome /var/lib/navidrome + ``` +4. Systemd-Service einrichten (optional). + +--- + +### Variante 2: \[\[Docker\]\] (empfohlen) + +```bash +docker run -d \ + --name=navidrome \ + -p 4533:4533 \ + -v /pfad/zu/deiner/musik:/music \ + -v /pfad/zu/navidrome/data:/data \ + deluan/navidrome:latest +``` + +--- + +## ⚙️ Ersteinrichtung + +- Navidrome läuft nun auf: +- Beim ersten Start wirst du aufgefordert, ein **Admin-Konto** anzulegen. +- Danach: Musikordner wird automatisch eingelesen (Metadaten, Cover, etc.). + +--- + +## 📌 Dinge, die man beachten sollte + +- **Firewall/Portfreigabe**: Wenn du von außen zugreifen willst, Port 4533 öffnen oder einen Reverse Proxy (nginx/traefik mit HTTPS) davor schalten. +- **Sicherung**: Datenbank & Konfigurationsordner `/data` regelmäßig sichern. +- **Rechte**: Musikordner muss für den Navidrome-Benutzer lesbar sein. +- **Transcoding**: Falls du FLAC → MP3 brauchst, sollte `ffmpeg` installiert sein. +- **Clients**: Nutze eine kompatible App für Smartphone-Streaming (z. B. Symfonium [Android], iSub [iOS]). + +--- + +\[\[Navidrome mit Strawberry 1\]\] \ No newline at end of file diff --git a/Computerkram/Linux/Paketinstallation in Linux-Distributionen.md b/Computerkram/Linux/Paketinstallation in Linux-Distributionen.md new file mode 100644 index 0000000..f141d2c --- /dev/null +++ b/Computerkram/Linux/Paketinstallation in Linux-Distributionen.md @@ -0,0 +1,99 @@ +## Debian-basierte Systeme (Ubuntu, Debian, Linux Mint, etc.) + +### APT (Advanced Package Tool) + +```bash +# Paketliste aktualisieren +sudo apt update + +# Einzelnes Paket installieren +sudo apt install paketname + +# Mehrere Pakete installieren +sudo apt install paket1 paket2 paket3 + +# System-Upgrade durchführen +sudo apt upgrade + +# Paket entfernen +sudo apt remove paketname + +# Paket komplett entfernen (inkl. Konfigurationsdateien) +sudo apt purge paketname + +# Nach Paketen suchen +apt search suchbegriff + +# Paketinformationen anzeigen +apt show paketname +``` + +### Alternative: APT-GET (ältere Syntax) +```bash +sudo apt-get update +sudo apt-get install paketname +sudo apt-get remove paketname +``` + +## Arch-basierte Systeme (Arch Linux, Manjaro, EndeavourOS, etc.) + +#Pacman (Package Manager) + +```bash +# Paketdatenbank synchronisieren +sudo pacman -Sy + +# System komplett aktualisieren +sudo pacman -Syu + +# Einzelnes Paket installieren +sudo pacman -S paketname + +# Mehrere Pakete installieren +sudo pacman -S paket1 paket2 paket3 + +# Paket entfernen +sudo pacman -R paketname + +# Paket mit Abhängigkeiten entfernen +sudo pacman -Rs paketname + +# Nach Paketen suchen +pacman -Ss suchbegriff + +# Installierte Pakete auflisten +pacman -Q + +# Paketinformationen anzeigen +pacman -Si paketname +``` + +### AUR (Arch User Repository) +Für AUR-Pakete wird ein AUR-Helper wie `yay` oder `paru` benötigt: + +```bash +# Mit yay installieren +yay -S paketname + +# Mit paru installieren +paru -S paketname +``` + +## Wichtige Parameter-Erklärungen + +| Debian (apt) | Arch (pacman) | Bedeutung | +|--------------|---------------|-----------| +| `update` | `-Sy` | Paketliste aktualisieren | +| `upgrade` | `-Su` | Installierte Pakete aktualisieren | +| `install` | `-S` | Paket installieren | +| `remove` | `-R` | Paket entfernen | +| `search` | `-Ss` | Nach Paketen suchen | +| `show` | `-Si` | Paketinformationen anzeigen | + +## Best Practices + +- **Immer vor Installation**: System aktualisieren +- **Debian**: `sudo apt update && sudo apt upgrade` +- **Arch**: `sudo pacman -Syu` + +> **Tipp**: Auf Arch-Systemen sollte man niemals `pacman -Sy paketname` ohne vorheriges vollständiges System-Update verwenden, da dies zu Abhängigkeitsproblemen führen kann. \ No newline at end of file diff --git a/Computerkram/Linux/SSH Verbindung in Linux.md b/Computerkram/Linux/SSH Verbindung in Linux.md new file mode 100644 index 0000000..9734014 --- /dev/null +++ b/Computerkram/Linux/SSH Verbindung in Linux.md @@ -0,0 +1,101 @@ + + +Um dich per **SSH** zwischen zwei Linux-Rechnern im Heimnetzwerk zu verbinden, gehst du so vor: + +--- + +### 1. SSH-Server installieren und aktivieren + +Auf dem Rechner, **zu dem du dich verbinden möchtest** (Zielrechner): + +```bash +sudo apt update && sudo apt install openssh-server -y # Ubuntu/Debian +sudo systemctl enable ssh +sudo systemctl start ssh +``` + +Auf Fedora/RHEL/Arch: + +```bash +sudo dnf install openssh-server -y # Fedora +sudo pacman -S openssh # Arch +sudo systemctl enable sshd +sudo systemctl start sshd +``` + +Status prüfen: + +```bash +systemctl status ssh +``` + +oder + +```bash +systemctl status sshd +``` + +--- + +### 2. IP-Adresse des Zielrechners herausfinden + +Auf dem Zielrechner: + +```bash +ip a +``` + +oder + +```bash +hostname -I +``` + +Beispielausgabe: `192.168.178.42` + +--- + +### 3. Verbindung vom Quellrechner herstellen + +Auf dem Rechner, von dem du zugreifen willst: + +```bash +ssh benutzername@192.168.178.42 +``` + +Dabei: + +- `benutzername` = Benutzerkonto auf dem Zielrechner +- `192.168.178.42` = IP-Adresse des Zielrechners im Heimnetz + +Beim ersten Mal wirst du gefragt, ob du den Host-Fingerprint akzeptieren willst → `yes`. Danach gibst du dein Passwort ein. + +--- + +### 4. (Optional) Passwortlose Anmeldung mit SSH-Key + +Falls du dich ohne Passwort anmelden willst: + +Auf dem Quellrechner: + +```bash +ssh-keygen -t ed25519 +``` + +(oder `rsa` falls gewünscht, einfach Enter drücken, um Standardpfad `~/.ssh/id_ed25519` zu nutzen) + +Dann den öffentlichen Schlüssel auf den Zielrechner kopieren: + +```bash +ssh-copy-id benutzername@192.168.178.42 +``` + +Danach kannst du dich einloggen ohne Passwort: + +```bash +ssh benutzername@192.168.178.42 +``` + +--- + +👉 Soll ich dir ein **kurzes Beispiel-Setup mit zwei Testbenutzern** schreiben, das du direkt im Heimnetz nachmachen kannst? \ No newline at end of file diff --git a/Computerkram/Linux/SSH-Schlüssel erzeugen.md b/Computerkram/Linux/SSH-Schlüssel erzeugen.md new file mode 100644 index 0000000..54b337c --- /dev/null +++ b/Computerkram/Linux/SSH-Schlüssel erzeugen.md @@ -0,0 +1,162 @@ +### 🔧 1. SSH-Schlüssel erzeugen + +Öffne ein Terminal und gib ein: + +```bash +ssh-keygen -t ed25519 -C "dein.name@beispiel.de" +``` + +- `-t ed25519`: moderner, sicherer Schlüsseltyp (alternativ: `rsa`). +- `-C`: Kommentar zur Identifikation (z. B. deine E-Mail). + +**Wenn gefragt:** + +- Speicherort bestätigen mit **Enter** (Standard: `~/.ssh/id_ed25519`). +- Optional ein **Passwort** setzen (empfohlen für zusätzliche Sicherheit). + +--- + +### 📤 2. Öffentlichen Schlüssel auf den Server kopieren + +Wenn du z. B. Zugriff auf `user@server.de` hast: + +```bash +ssh-copy-id user@server.de +``` + +Falls `ssh-copy-id` nicht installiert ist, kannst du den Schlüssel auch manuell übertragen: + +```bash +cat ~/.ssh/id_ed25519.pub +``` + +Dann den Inhalt in die Datei `~/.ssh/authorized_keys` auf dem Server einfügen. + +--- + +### 🔐 3. Mit dem Server verbinden + +Danach kannst du dich einfach per SSH einloggen: + +```bash +ssh user@server.de +``` + +Du wirst **nicht mehr nach dem Passwort des Servers** gefragt – nur ggf. nach der Passphrase deines privaten Schlüssels. + +--- + +### 🧩 (Optional) 4. SSH-Agent verwenden + +Damit du die Passphrase nicht ständig eingeben musst: + +```bash +eval "$(ssh-agent -s)" +ssh-add ~/.ssh/id_ed25519 +``` + +--- +Wenn `git push` weiterhin nach einem Passwort fragt, liegt das fast immer daran, dass dein Repository **über HTTPS statt SSH** verbunden ist. + +Lass uns das prüfen und beheben 👇 + +--- + +## 🔎 1️⃣ Prüfen, welche Remote-URL verwendet wird + +Im Repository: + +```bash +git remote -v +``` + +Wenn du etwas siehst wie: + +``` +https://github.com/USERNAME/REPO.git +``` + +➡ Dann nutzt du **HTTPS** – deshalb wird ein Passwort (bzw. Token) verlangt. + +Wenn dort steht: + +``` +git@github.com:USERNAME/REPO.git +``` + +➡ Das ist korrekt (SSH). + +--- + +## 🔁 2️⃣ Remote von HTTPS auf SSH umstellen + +Ersetze die URL mit der SSH-Version: + +```bash +git remote set-url origin git@github.com:USERNAME/REPO.git +``` + +Danach nochmal testen: + +```bash +git push +``` + +--- + +## 🧪 3️⃣ SSH-Verbindung separat testen + +```bash +ssh -T git@github.com +``` + +Du solltest eine Meldung bekommen wie: + +``` +Hi USERNAME! You've successfully authenticated... +``` + +Wenn nicht, sag mir bitte die Fehlermeldung. + +--- + +## 🔐 4️⃣ Falls SSH korrekt ist, aber trotzdem Passwort kommt + +Dann prüfen: + +### Läuft der SSH-Agent? + +```bash +ssh-add -l +``` + +Wenn dort steht: + +``` +The agent has no identities. +``` + +Dann: + +```bash +ssh-add ~/.ssh/id_ed25519 +``` + +--- + +## 🛠 5️⃣ Debug-Modus (wenn es immer noch nicht klappt) + +```bash +ssh -vT git@github.com +``` + +Das zeigt, welcher Key wirklich benutzt wird. + +--- + +### 💡 90% der Fälle: + +Das Repository wurde ursprünglich per HTTPS geklont. + +Wenn du möchtest, kannst du mir die Ausgabe von +`git remote -v` posten – dann sage ich dir exakt, was los ist. \ No newline at end of file diff --git a/Computerkram/Linux/Strawberry.md b/Computerkram/Linux/Strawberry.md new file mode 100644 index 0000000..365a0a9 --- /dev/null +++ b/Computerkram/Linux/Strawberry.md @@ -0,0 +1,137 @@ +Strawberry ist ein **Musikplayer und -manager** für [[Linux]] (auch für Windows und macOS verfügbar), der sich auf **lokale Musiksammlungen** konzentriert. Er ist ein Fork von _Clementine_, das wiederum auf _Amarok_ basiert. Strawberry richtet sich vor allem an Nutzer, die eine **große Sammlung an Musikdateien (MP3, FLAC, OGG, etc.) lokal verwalten** möchten – im Gegensatz zu Playern, die stark auf Streaming setzen. + +--- + +## 🎯 Zweck von Strawberry + +- **Abspielen von Musikdateien** in allen gängigen Formaten. + +- **Bibliotheksverwaltung**: Organisieren großer Sammlungen anhand von Metadaten, Tags und Ordnerstrukturen. + +- **Metadatenverwaltung**: Bearbeiten von Tags, Laden von Cover-Artworks, Abgleich mit Online-Datenbanken (z. B. MusicBrainz). + +- **Wiedergabelisten**: Erstellen und Verwalten komplexer Playlists. + +- **Audiowiedergabe in hoher Qualität** mit Unterstützung von Hi-Res-Formaten. + +- **Externe Dienste**: Scrobbling zu Last.fm, Libre.fm oder ListenBrainz. + + +--- + +## ⚙️ Funktionen + +- Unterstützung für FLAC, MP3, OGG, WAV, WMA, AAC u. v. m. + +- Wiedergabe mit **GStreamer** (gute Audioqualität, viele Codecs). + +- **Tag-Editor** für ID3, Vorbis- und FLAC-Tags. + +- Automatisches Laden von **Album-Covern**. + +- **EQ und ReplayGain**-Unterstützung. + +- **Wiedergabelisten** im M3U-, XSPF- und PLS-Format. + +- **Gerätesynchronisation**: Musik auf mobile Player kopieren. + +- **Streaming-Radio** (einfache Integration, aber nicht Hauptfokus). + + +--- + +## ✅ Vorteile + +- **Fokus auf lokale Musik** – ideal für Sammler, die ihre eigene Bibliothek pflegen. + +- **Schnell und ressourcenschonend** im Vergleich zu schwergewichtigeren Lösungen wie Amarok. + +- **Moderne Code-Basis**: aktiver Fork von Clementine mit Bugfixes und Verbesserungen. + +- **Hohe Audioqualität** mit vielen Formaten und Hi-Res-Support. + +- **Cross-Platform**: Linux, Windows, macOS. + +- **Keine Zwangs-Cloud-Anbindung** wie bei Spotify & Co. + + +--- + +## ❌ Nachteile + +- **Kein nativer Streaming-Fokus** (nur begrenzte Unterstützung für Online-Dienste, keine direkte Spotify-/Apple-Music-Integration). + +- **Eher klassische Oberfläche** – wirkt funktional, aber nicht besonders modern/minimalistisch. + +- **Weniger Community als bei großen Projekten** (z. B. Rhythmbox oder VLC). + +- **Kein eigener mobiler Client** – Synchronisation nur über Dateiübertragung. + + +--- + +## 💻 Installation + +### Unter Ubuntu/Debian + +```bash +sudo apt install strawberry +``` + +Falls nicht im Standard-Repo (bei älteren Versionen): + +```bash +sudo add-apt-repository ppa:jonaski/strawberry +sudo apt update +sudo apt install strawberry +``` + +### Unter Fedora + +```bash +sudo dnf install strawberry +``` + +### Unter Arch Linux / Manjaro + +```bash +sudo pacman -S strawberry +``` + +### Alternative: Flatpak (universell) + +```bash +flatpak install flathub org.strawberrymusicplayer.strawberry +``` + +--- + +## 🔧 Einrichtung + +1. **Musikordner hinzufügen**: Beim ersten Start fragt Strawberry nach Verzeichnissen, in denen Musik liegt. + +2. **Bibliothek scannen**: Die Dateien werden eingelesen und nach Tags sortiert. + +3. **Audioausgabe konfigurieren**: In den Einstellungen (z. B. ALSA, PulseAudio, PipeWire auswählen). + +4. **Metadaten-Services aktivieren**: Verknüpfung mit MusicBrainz, Last.fm oder Libre.fm, wenn gewünscht. + +5. **Wiedergabelisten und Cover laden**: Automatisches Suchen und Speichern aktivieren. + + +--- + +## 📌 Was man beachten sollte + +- Strawberry ist für **Sammler und Audiophile** gedacht – wenn man hauptsächlich Spotify oder YouTube nutzt, ist es weniger passend. + +- Gute Organisation der Musikordner und Tags erleichtert die Verwaltung erheblich. + +- Bei **Hi-Res-Audio**: Prüfen, ob das Audiosystem (ALSA/PipeWire) korrekt konfiguriert ist. + +- Für große Bibliotheken (>100.000 Tracks) sollte man auf genügend RAM und eine SSD achten, sonst wird die Suche langsam. + + +--- + +👉 Soll ich dir eine Schritt-für-Schritt-Anleitung schreiben, wie du Strawberry nach der Installation optimal für eine große Musiksammlung einrichtest (inkl. Cover, Tags, Audio-Einstellungen)? \ No newline at end of file diff --git a/Computerkram/Linux/Subsonic-API.md b/Computerkram/Linux/Subsonic-API.md new file mode 100644 index 0000000..393137b --- /dev/null +++ b/Computerkram/Linux/Subsonic-API.md @@ -0,0 +1,119 @@ +Perfekt – dann ist eine Subsonic-kompatible Library genau das, was du suchst 👍 + +Für [[Python]] gibt es z. B. [`py-sonic`](https://github.com/crustymonkey/py-sonic). +Die ist zwar nicht mehr super aktiv gepflegt, funktioniert aber mit [[Navidrome]] problemlos, weil Navidrome die [[Subsonic-API]] spricht. + +--- + +## Installation + +```bash +pip install py-sonic +``` + +--- + +## Grund-Setup + +```python +from pysonic.connection import Connection + +# Verbindung aufbauen +conn = Connection( + host="http://localhost:4533", + username="meinuser", + password="meinpass", + api_version="1.16.1", + client_name="pyclient" +) +``` + +--- + +## Anwendungsfälle + +### 1. Playlist erstellen oder öffnen + +```python +# Neue Playlist +playlist = conn.create_playlist("Importierte M3U Playlist") + +# Alle Playlists abfragen +all_playlists = conn.get_playlists() +``` + +### 2. Tracks suchen (z. B. per Filename, Titel, Artist) + +```python +search = conn.search2(query="Songtitel", songCount=5) +for song in search['song']: + print(song['id'], song['title'], song['artist']) +``` + +### 3. Track zur Playlist hinzufügen + +```python +conn.update_playlist( + playlist_id=playlist['id'], + song_id=["12345", "67890"] # mehrere IDs möglich +) +``` + +### 4. Stern vergeben + +```python +conn.star("12345") # Song-ID +``` + +### 5. Bookmark setzen + +```python +conn.create_bookmark("12345", position=60000, comment="Kapitel 1") +``` + +--- + +## Workflow: M3U importieren + +Du kannst einfach durch deine `.m3u`-Datei iterieren, für jede Zeile versuchen, den Track im Navidrome zu finden, und dann Aktionen ausführen: + +```python +def import_m3u_to_navidrome(m3u_path, playlist_name): + # Playlist anlegen + playlist = conn.create_playlist(playlist_name) + playlist_id = playlist['id'] + + with open(m3u_path, encoding="utf-8") as f: + for line in f: + if line.startswith("#") or not line.strip(): + continue + filename = line.strip().split("/")[-1] # nur Dateiname + + # Suche im Server + search = conn.search2(query=filename, songCount=1) + if 'song' in search and search['song']: + song = search['song'][0] + song_id = song['id'] + + # Playlist hinzufügen + conn.update_playlist(playlist_id=playlist_id, song_id=[song_id]) + + # Stern setzen + conn.star(song_id) + + # Bookmark bei 0 (Startpunkt) + conn.create_bookmark(song_id, position=0, comment="Importiert aus M3U") + + print(f"→ {filename} gefunden und verarbeitet.") + else: + print(f"⚠ {filename} nicht gefunden.") +``` + +--- + +👉 Damit hättest du ziemlich genau deinen beschriebenen Workflow: +M3U → Tracks auflösen → Playlist + Sterne + Bookmarks automatisch setzen. + +--- + +Soll ich dir ein **vollständiges Script** bauen, das direkt eine `.m3u` einliest, die passende Playlist erstellt und alle drei Aktionen (Playlist-Eintrag, Stern, Bookmark) in einem Durchlauf macht? \ No newline at end of file diff --git a/Computerkram/Linux/Synchronisation & Backup.md b/Computerkram/Linux/Synchronisation & Backup.md new file mode 100644 index 0000000..4985b0f --- /dev/null +++ b/Computerkram/Linux/Synchronisation & Backup.md @@ -0,0 +1,472 @@ +Alles klar – ich gebe dir eine ausführliche Übersicht über **Dateisynchronisation und Backups unter Linux**, gegliedert nach typischen Anwendungsfällen (1-way Backup, 2-way Sync, Spezialfälle). Dazu zeige ich dir jeweils **interessante Funktionen**, **geeignete Tools** und **Code-Beispiele**, die du direkt ausprobieren kannst. + +--- + +# 🔧 Dateisynchronisation und Backup unter Linux + +## 1. Grundsätzliche Anwendungsfälle + +1. **Backup (1-way Synchronisation)** + + - Ziel: Sicherung von Daten von Quelle → Ziel. + + - Änderungen im Quellordner werden ins Ziel kopiert. + + - Änderungen im Ziel haben keine Wirkung zurück. + + - Typisch für: + + - Regelmäßige Datensicherungen (lokal oder auf Server/NAS) + + - Snapshots und inkrementelle Backups + +2. **Zwei-Wege-Synchronisation (2-way)** + + - Ziel: Quell- und Zielordner sind identisch. + + - Änderungen in beiden Richtungen werden abgeglichen. + + - Typisch für: + + - Zusammenarbeit zwischen Geräten + + - Synchronisation von Arbeitsordnern mit Netzwerkfreigaben oder Cloud + +3. **Weitere Anwendungsbeispiele** + + - **Offsite-Backup** (z. B. automatisches Backup auf einen entfernten Server via SSH) + + - **Versionierte Backups** (Aufbewahrung älterer Stände) + + - **On-the-fly Synchronisation** (z. B. Watcher, der beim Speichern sofort sync’ed) + + - **Mobile Synchronisation** (z. B. Laptop ↔ NAS, USB-Stick ↔ Rechner) + + +--- + +## 2. Tools für 1-way Backups + +### a) **rsync** (Klassiker) + +Das meistgenutzte Werkzeug, effizient und flexibel. + +**Einfaches Backup:** + +```bash +rsync -avh /home/user/Dokumente/ /media/backup/Dokumente/ +``` + +- `-a` = Archivmodus (erhält Rechte, Zeiten, Links) + +- `-v` = verbose + +- `-h` = menschenlesbare Größen + + +**Mit Löschen (Spiegelung):** + +```bash +rsync -avh --delete /home/user/Dokumente/ /media/backup/Dokumente/ +``` + +→ Dateien, die in Quelle gelöscht wurden, werden auch im Ziel gelöscht. + +**Über SSH (z. B. auf NAS oder Server):** + +```bash +rsync -avz /home/user/Dokumente/ user@server:/backup/Dokumente/ +``` + +- `-z` = Kompression + + +**Interessante Funktionen:** + +- `--exclude "*.tmp"` → bestimmte Dateien ignorieren + +- `--progress` → Fortschrittsanzeige + +- `--link-dest` → inkrementelle Backups mit Hardlinks (ähnlich Time Machine) + + +--- + +### b) **borgbackup** (für versionierte, komprimierte, verschlüsselte Backups) + +Ideal für langfristige Backups mit Versionierung. + +```bash +borg init --encryption=repokey /media/backup/repo +borg create --progress /media/backup/repo::2025-09-26 /home/user/Dokumente +``` + +Später kannst du ältere Versionen wiederherstellen. + +--- + +## 3. Tools für 2-way Synchronisation + +### a) **unison** + +Ein Klassiker für bidirektionale Synchronisation. + +**Einfacher Start:** + +```bash +unison /home/user/Dokumente ssh://user@server//home/user/Dokumente +``` + +- Erkennt Änderungen auf beiden Seiten + +- Fragt bei Konflikten nach + +- Arbeitet ähnlich wie `rsync`, aber **beidseitig** + + +**Dauerhafte Konfiguration:** +In `~/.unison/default.prf`: + +``` +root = /home/user/Dokumente +root = ssh://user@server//home/user/Dokumente +auto = true +batch = true +``` + +Dann reicht: + +```bash +unison +``` + +--- + +### b) **Syncthing** (komfortabel mit Weboberfläche) + +- Peer-to-Peer Synchronisation (Ende-zu-Ende verschlüsselt) + +- Cross-Platform (Linux, Windows, Android, macOS) + +- Ideal für nahtlose Syncs ohne manuellen Eingriff + + +Installation: + +```bash +sudo apt install syncthing +syncthing +``` + +→ Startet Weboberfläche auf [http://127.0.0.1:8384](http://127.0.0.1:8384) + +--- + +## 4. Automatisierung + +### a) Cron-Jobs für regelmäßige Backups + +Beispiel: Täglich um 3 Uhr ein rsync-Backup: + +```bash +0 3 * * * rsync -avh --delete /home/user/Dokumente/ /media/backup/Dokumente/ +``` + +(`crontab -e`) + +### b) systemd Timer (moderner als Cron) + +Service-Unit (`/etc/systemd/system/backup.service`): + +```ini +[Unit] +Description=Backup Dokumente + +[Service] +ExecStart=/usr/bin/rsync -avh --delete /home/user/Dokumente/ /media/backup/Dokumente/ +``` + +Timer (`/etc/systemd/system/backup.timer`): + +```ini +[Unit] +Description=Backup Timer + +[Timer] +OnCalendar=daily +Persistent=true + +[Install] +WantedBy=timers.target +``` + +Aktivieren: + +```bash +sudo systemctl enable --now backup.timer +``` + +--- + +## 5. Zusammenfassung der interessantesten Funktionen + +- **rsync** → universell, effizient, für Backups und Spiegelungen + +- **borgbackup** → versioniert, verschlüsselt, platzsparend + +- **unison** → 2-way Sync mit Konfliktlösung + +- **syncthing** → benutzerfreundlich, kontinuierliche Synchronisation + + +--- + +👉 Tipp: +Wenn du **nur Backups** brauchst → `rsync` oder `borg`. +Wenn du **aktive Ordner synchron halten willst** → `unison` oder `syncthing`. + +--- + +Soll ich dir zum Einstieg ein **komplettes Setup-Skript für ein automatisches tägliches Backup mit rsync** schreiben, das du direkt verwenden kannst? +Sehr gute Fragen 👍 — ich gehe das mit dir systematisch durch. + +--- + +# 🔄 Unison: Verhalten, Hintergrundbetrieb & Performance + +## 1. Läuft Unison permanent im Hintergrund? + +Unison an sich ist **kein permanenter Daemon** wie etwa Syncthing. +Es funktioniert normalerweise so: + +- Du startest Unison → es vergleicht Quelle und Ziel → synchronisiert → beendet sich. + +- Du kannst es per Cron, systemd-Timer oder manuell regelmäßig ausführen. + +- Es gibt aber einen **"Unison-GUI/Repeat-Modus"**, bei dem es in einer Schleife läuft und z. B. alle 10 Sekunden die Verzeichnisse prüft. + + +Beispiel für wiederholte Synchronisation: + +```bash +unison default -repeat watch +``` + +- `-repeat watch` = Unison nutzt OS-Funktionalitäten (inotify auf Linux), um Änderungen sofort zu erkennen. + +- `-repeat 10` = alternativ: Polling alle 10 Sekunden. + + +Damit verhält sich Unison _fast_ wie Syncthing, aber ist weniger komfortabel, weil es keinen richtigen Daemon hat. + +--- + +## 2. Start bei Systemstart + +Damit Unison automatisch startet, kannst du es mit **systemd** einrichten. + +### Beispiel: systemd Service-Datei + +`~/.config/systemd/user/unison.service` + +```ini +[Unit] +Description=Unison sync service +After=network.target + +[Service] +ExecStart=/usr/bin/unison default -repeat watch +Restart=always +RestartSec=5 + +[Install] +WantedBy=default.target +``` + +Dann aktivieren: + +```bash +systemctl --user enable --now unison.service +``` + +→ Jetzt läuft Unison beim Login des Users automatisch und überwacht die definierten Profile. + +--- + +## 3. Performance Impact + +Die Performance hängt von der Betriebsart ab: + +- **Einmalige Ausführung (Standard)** + + - Minimaler Impact, nur während der Synchronisation. + + - Nutzt Hashing/Datei-Checksummen, um Änderungen effizient zu erkennen. + + - Bei großen Verzeichnissen ist der **erste Lauf** teuer (voller Indexaufbau), danach werden nur Änderungen geprüft. + +- **Dauerbetrieb mit `-repeat watch`** + + - Nutzt `inotify` → kaum CPU-Last, da nur Änderungen getriggert werden. + + - Speicherbedarf: wenige Dutzend MB RAM. + + - CPU-Last: fast 0, außer wenn aktiv synchronisiert wird. + +- **Dauerbetrieb mit `-repeat 10` (Polling)** + + - Alle 10 Sekunden kompletter Scan → deutlich mehr I/O bei vielen Dateien. + + - Sollte nur verwendet werden, wenn `inotify` nicht funktioniert (z. B. bei Netzwerk-Dateisystemen). + + +**Kurz:** + +- Lokale Ordner: `-repeat watch` → sehr effizient + +- Netzwerk-Mounts (NFS, SMB): oft kein inotify → Polling nötig, etwas schwerer + + +--- + +## 4. Fazit + +- Unison ist **keine Always-on-Synchronisation wie Syncthing**, aber mit `-repeat watch` + systemd lässt es sich quasi gleichwertig nutzen. + +- Performance-Impact ist sehr gering, solange du `watch` nutzt. + +- Für **regelmäßige Backups** → Cron oder systemd Timer reicht. + +- Für **nahezu Echtzeit-Sync** → `-repeat watch` + systemd Service ist die beste Lösung. + + +--- + + +## 1. Voraussetzung: Config-Datei + +Ja, korrekt ✅ +Der Aufruf + +```bash +unison default -repeat watch +``` + +setzt voraus, dass du eine Konfigurationsdatei `~/.unison/default.prf` hast. +Dort definierst du z. B.: + +```txt +root = /home/user/Dokumente +root = ssh://user@server//home/user/Dokumente + +auto = true +batch = true +``` + +- **`auto = true`** → versucht, Konflikte automatisch zu lösen (kein Nachfragen bei eindeutigen Fällen). + +- **`batch = true`** → führt ohne Interaktion aus. + + - Falls Konflikte auftreten, entscheidet er nach den Regeln oder verweigert Sync. + + - Ohne `batch` würdest du wieder Fragen im Terminal sehen. + + +👉 Empfehlung: Für systemd immer `auto = true` und `batch = true` setzen, sonst blockiert der Prozess. + +--- + +## 2. Rückfragen vermeiden (Default-Verhalten) + +Wie du beobachtet hast, fragt Unison bei `unison [quelle] [ziel]` ohne Konfig bei **Konflikten** („Welche Version behalten?“). + +- Mit **Konfig + batch + auto** → keine Rückfragen. + +- Du kannst zusätzlich Regeln setzen, z. B.: + + +```txt +prefer = newer # Immer die neuere Version behalten +prefer = /home/user # Lokale Version gewinnt +``` + +Das ist wichtig für den systemd-Einsatz, weil ein Dienst nicht sinnvoll auf Eingaben warten kann. + +--- + +## 3. Logging + +### a) Standardmäßig + +Unison schreibt **keine dauerhaften Logs** von sich aus. +Die Ausgaben gehen in `stdout/stderr` → wenn du es manuell startest, siehst du es im Terminal. + +### b) Mit systemd + +systemd fängt alles auf → mit + +```bash +journalctl --user -u unison.service +``` + +siehst du die Logs. +Wenn dir das reicht, brauchst du nichts extra. + +### c) Eigene Logdateien + +Du kannst in der `.prf`-Datei angeben: + +```txt +log = /var/log/unison/unison.log +``` + +oder direkt beim Start per `ExecStart`: + +```ini +ExecStart=/usr/bin/unison default -repeat watch -logfile /var/log/unison/unison.log +``` + +### d) Alte Logs automatisch löschen + +Unison selbst rotiert keine Logs, aber systemd oder `logrotate` kann das übernehmen. +Beispiel `logrotate`-Konfig (`/etc/logrotate.d/unison`): + +``` +/var/log/unison/unison.log { + daily + rotate 30 + compress + missingok + notifempty + create 640 user user +} +``` + +→ Hält 30 Tage Logs, dann werden sie komprimiert/gelöscht. + +Wenn du lieber pro Sitzung in `/tmp` loggen willst: + +```ini +ExecStart=/usr/bin/unison default -repeat watch -logfile /tmp/unison-%u.log +``` + +und ein Cronjob/systemd-Timer löscht alte Dateien: + +```bash +find /tmp -name 'unison-*.log' -mtime +30 -delete +``` + +--- + +## 4. Fazit + +- **Ja**, Config-Datei nötig → dort Batch/Auto einstellen. + +- **Default-Verhalten einstellen** mit `prefer`-Regeln, sonst blockieren Konflikte. + +- **Logs**: systemd-Journal reicht oft, alternativ eigene Logdatei + logrotate. + + +--- + +👉 Soll ich dir eine **komplette Beispielkonfig `default.prf` + passende systemd-Service-Datei** basteln, die direkt „Headless-Sync im Hintergrund“ macht inkl. Log-Rotation? \ No newline at end of file diff --git a/Computerkram/Linux/Timeshift.md b/Computerkram/Linux/Timeshift.md new file mode 100644 index 0000000..b740eed --- /dev/null +++ b/Computerkram/Linux/Timeshift.md @@ -0,0 +1,230 @@ +# Timeshift Kommandozeilen-Nutzung + +## Überblick +Timeshift ist ein Backup-Tool für Linux-Systeme, das System-Snapshots erstellt. Es kann sowohl über eine grafische Oberfläche als auch über die Kommandozeile verwendet werden. + +## Installation +```bash +# Ubuntu/Debian +sudo apt update && sudo apt install timeshift + +# Arch Linux +sudo pacman -S timeshift + +# Fedora/CentOS +sudo dnf install timeshift +``` + +## Grundlegende Konfiguration + +### Initialisierung +```bash +# Timeshift einrichten (wählt automatisch RSYNC oder BTRFS) +sudo timeshift --check + +# Konfiguration anzeigen +sudo timeshift --list-config +``` + +### Backup-Typ festlegen +```bash +# RSYNC-Modus (Standard für ext4) +sudo timeshift --rsync + +# BTRFS-Modus (für BTRFS-Dateisysteme) +sudo timeshift --btrfs +``` + +## Snapshots erstellen + +### Manuellen Snapshot erstellen +```bash +# Einfacher Snapshot +sudo timeshift --create + +# Snapshot mit Kommentar +sudo timeshift --create --comments "Vor System-Update" + +# Snapshot mit spezifischem Namen +sudo timeshift --create --comments "Pre-Kernel-Update-$(date +%Y%m%d)" +``` + +### Automatische Snapshots konfigurieren +```bash +# Tägliche Snapshots aktivieren +sudo timeshift --snapshot-device /dev/sda1 --schedule-daily + +# Wöchentliche Snapshots +sudo timeshift --schedule-weekly + +# Monatliche Snapshots +sudo timeshift --schedule-monthly +``` + +## Snapshots verwalten + +### Snapshots auflisten +```bash +# Alle verfügbaren Snapshots anzeigen +sudo timeshift --list + +# Detaillierte Liste +sudo timeshift --list --verbose +``` + +### Snapshot-Informationen anzeigen +```bash +# Informationen zu einem spezifischen Snapshot +sudo timeshift --list | grep "2024-01-15" +``` + +## System wiederherstellen + +### Komplette Systemwiederherstellung +```bash +# Neuesten Snapshot wiederherstellen +sudo timeshift --restore + +# Spezifischen Snapshot wiederherstellen +sudo timeshift --restore --snapshot "2024-01-15_18-30-45" + +# Wiederherstellung mit Bestätigung +sudo timeshift --restore --snapshot "2024-01-15_18-30-45" --skip-grub +``` + +### Einzelne Dateien wiederherstellen +```bash +# Snapshot mounten (nur-lesen) +sudo timeshift --restore --snapshot "2024-01-15_18-30-45" --clone + +# Dann Dateien manuell kopieren +cp /timeshift/snapshots/2024-01-15_18-30-45/localhost/path/to/file /original/path/ +``` + +## TTY-Sitzung (Notfall-Wiederherstellung) + +### Zugang zur TTY +```bash +# Wechsel zu TTY (Strg+Alt+F1 bis F6) +# Oder über SSH wenn verfügbar +``` + +### Wiederherstellung in TTY +```bash +# 1. Als root anmelden +sudo su - + +# 2. Snapshots auflisten +timeshift --list + +# 3. System wiederherstellen +timeshift --restore --snapshot "SNAPSHOT_NAME" + +# 4. System neustarten +reboot +``` + +### Notfall-Boot von Live-USB +```bash +# 1. Live-USB booten +# 2. Festplatte mounten +sudo mount /dev/sda1 /mnt + +# 3. Timeshift auf Live-System installieren +sudo apt update && sudo apt install timeshift + +# 4. Wiederherstellung auf gemountete Partition +sudo timeshift --restore --target-device /dev/sda1 +``` + +## Nützliche Optionen + +### Backup-Ausschlüsse konfigurieren +```bash +# Bestimmte Verzeichnisse ausschließen +sudo timeshift --exclude /home/user/Downloads +sudo timeshift --exclude /tmp +sudo timeshift --exclude /var/cache +``` + +### Aufbewahrungsrichtlinien +```bash +# Maximale Anzahl Snapshots begrenzen +sudo timeshift --max-snapshots 5 + +# Alte Snapshots automatisch löschen +sudo timeshift --delete-old +``` + +### Snapshot löschen +```bash +# Spezifischen Snapshot löschen +sudo timeshift --delete --snapshot "2024-01-15_18-30-45" + +# Alle bis auf die letzten 3 löschen +sudo timeshift --delete-old --max-snapshots 3 +``` + +## Automatisierung mit Cron + +### Tägliche Backups einrichten +```bash +# Crontab bearbeiten +sudo crontab -e + +# Tägliches Backup um 2:00 Uhr +0 2 * * * /usr/bin/timeshift --create --comments "Daily-Auto-$(date +\%Y\%m\%d)" && /usr/bin/timeshift --delete-old --max-snapshots 7 +``` + +## Monitoring und Logs + +### Status überprüfen +```bash +# Timeshift-Status +sudo timeshift --check + +# Logs anzeigen +sudo journalctl -u timeshift +tail -f /var/log/timeshift.log +``` + +### Speicherplatz überwachen +```bash +# Snapshot-Größen anzeigen +du -sh /timeshift/snapshots/* + +# Verfügbaren Speicher prüfen +df -h /timeshift +``` + +## Troubleshooting + +### Häufige Probleme +```bash +# Berechtigungen reparieren +sudo timeshift --check + +# Cache leeren +sudo rm -rf /tmp/timeshift* + +# Snapshot-Index reparieren +sudo timeshift --delete-old --scripted +``` + +### Recovery bei korrupten Snapshots +```bash +# Snapshot-Konsistenz prüfen +sudo timeshift --list --check-snapshots + +# Defekte Snapshots entfernen +sudo timeshift --delete --snapshot "CORRUPT_SNAPSHOT" +``` + +--- + +**Wichtige Hinweise:** +- Immer mit `sudo` ausführen +- Vor wichtigen Systemänderungen Snapshots erstellen +- Regelmäßig alte Snapshots löschen (Speicherplatz) +- Bei BTRFS-Systemen BTRFS-Modus verwenden +- Boot-Snapshots für kritische Updates erstellen \ No newline at end of file diff --git a/Computerkram/Linux/USB-Stick unter Linux per Bash formatieren.md b/Computerkram/Linux/USB-Stick unter Linux per Bash formatieren.md new file mode 100644 index 0000000..f3e7a1f --- /dev/null +++ b/Computerkram/Linux/USB-Stick unter Linux per Bash formatieren.md @@ -0,0 +1,111 @@ +Diese Anleitung zeigt, wie du einen USB-Stick über die Kommandozeile sicher formatierst. +⚠️ **Achtung:** Falsche Gerätenamen können zu Datenverlust führen. + +--- + +## 1. USB-Stick identifizieren + +Liste alle Laufwerke auf: + +```bash +lsblk +``` + +Beispielausgabe: + +``` +sda 500G +sdb 16G ← USB-Stick +``` + +> **Merke dir den Gerätenamen des USB-Sticks**, z. B. `/dev/sdb`. + +--- + +## 2. USB-Stick aushängen + +Falls der Stick automatisch eingehängt wurde: + +```bash +sudo umount /dev/sdb* +``` + +--- + +## 3. Optional: Stick vollständig säubern + +Entfernt alte Partitionstabellen: + +```bash +sudo wipefs -a /dev/sdb +``` + +--- + +## 4. Neue Partitionstabelle anlegen (MBR) + +```bash +sudo parted /dev/sdb mklabel msdos +``` + +--- + +## 5. Eine neue Partition über den gesamten Stick erstellen + +```bash +sudo parted -a optimal /dev/sdb mkpart primary fat32 0% 100% +``` + +> Wenn du ein anderes Dateisystem planst, kannst du `fat32` durch einen anderen Typ ersetzen (z. B. `ext4`). + +--- + +## 6. Dateisystem erstellen + +### FAT32 (am kompatibelsten) + +```bash +sudo mkfs.vfat -F 32 /dev/sdb1 +``` + +### exFAT + +```bash +sudo mkfs.exfat /dev/sdb1 +``` + +### NTFS + +```bash +sudo mkfs.ntfs -Q /dev/sdb1 +``` + +### ext4 (für Linux-Systeme) + +```bash +sudo mkfs.ext4 /dev/sdb1 +``` + +--- + +## 7. Stick entfernen und neu verbinden + +Der Stick wird beim Wiedereinstecken normalerweise automatisch eingehängt. + +--- + +## 8. Optional: Label setzen + +```bash +sudo fatlabel /dev/sdb1 MEINUSB +``` + +Für ext4: + +```bash +sudo e2label /dev/sdb1 MEINUSB +``` + +--- + +Wenn du möchtest, erstelle ich dir auch eine Version als **Obsidian-Template**, z. B. mit Variablen oder Checkboxen. \ No newline at end of file diff --git a/Computerkram/Linux/VIM Cheat Sheet.md b/Computerkram/Linux/VIM Cheat Sheet.md new file mode 100644 index 0000000..d79520f --- /dev/null +++ b/Computerkram/Linux/VIM Cheat Sheet.md @@ -0,0 +1,458 @@ +Hier ist ein kompaktes, aber vollständiges **VIM Cheat Sheet** 📝 + +--- + +## 🔹 Modi in VIM + +|Modus|Bedeutung|Wechsel| +|---|---|---| +|**Normal Mode**|Navigation & Befehle|`Esc`| +|**Insert Mode**|Texteingabe|`i`, `a`, `o`, etc.| +|**Visual Mode**|Text markieren|`v`, `V`, `Ctrl+v`| +|**Command Mode**|Speichern, Beenden, etc.|`:`| + +--- + +## 🔹 Insert Mode Befehle + +|Befehl|Wirkung| +|---|---| +|`i`|Vor Cursor einfügen| +|`a`|Nach Cursor einfügen| +|`I`|Am Zeilenanfang einfügen| +|`A`|Am Zeilenende einfügen| +|`o`|Neue Zeile unterhalb| +|`O`|Neue Zeile oberhalb| + +--- + +## 🔹 Navigation (Normal Mode) + +### Zeichenweise + +``` +h ← j ↓ k ↑ l → +``` + +### Wortweise + +``` +w nächstes Wort +b vorheriges Wort +e Wortende +``` + +### Zeilenweise + +``` +0 Zeilenanfang +^ Erstes Nicht-Leerzeichen +$ Zeilenende +``` + +### Datei + +``` +gg Anfang der Datei +G Ende der Datei +:n Gehe zu Zeile n +``` + +--- + +## 🔹 Löschen + +|Befehl|Wirkung| +|---|---| +|`x`|Zeichen löschen| +|`dd`|Zeile löschen| +|`dw`|Wort löschen| +|`d$`|Bis Zeilenende löschen| +|`d0`|Bis Zeilenanfang löschen| + +💡 Kombination: `d` + Bewegung funktioniert immer +(z.B. `d3w` = 3 Wörter löschen) + +--- + +## 🔹 Kopieren & Einfügen + +|Befehl|Wirkung| +|---|---| +|`yy`|Zeile kopieren| +|`yw`|Wort kopieren| +|`p`|Nach Cursor einfügen| +|`P`|Vor Cursor einfügen| + +#### Register +Vor alle Kopieren oder Einfügen Befehle kann ein `"3` gestellt werden, um ins 3. Register zu schreiben bzw. daraus heraus zu lesen. Z.b. kopiert `"7yw` das Wort ins 7. Register und `"4p` fügt das 4. Register nach dem Curser ein. +💡 Das spezielle Register `+`/`*` ist das System-Clipboard, sehr Praktisch zum Austausch von Text mit anderen Programmen +Alle Register ansehen: `:reg` +💡 Das spezielle Register `%` enthält den aktuellen Dateipfad -> aktuelle Dateipfad in System-Clipboard: `:let @+=@%`. + + +--- + +## 🔹 Undo / Redo + +``` +u Undo +Ctrl+r Redo +``` + +--- + +## 🔹 Visual Mode + +|Befehl|Wirkung| +|---|---| +|`v`|Zeichenweise markieren| +|`V`|Ganze Zeile markieren| +|`Ctrl+v`|Block markieren| + +Nach Markierung: + +``` +d löschen +y kopieren +> einrücken +< ausrücken +``` + +--- + +## 🔹 Suchen & Ersetzen + +``` +/text Vorwärts suchen +?text Rückwärts suchen +n Nächstes Ergebnis +N Vorheriges Ergebnis +``` + +Ersetzen: + +``` +:%s/alt/neu/g Ganze Datei +:s/alt/neu/g Aktuelle Zeile +:%s/alt/neu/gc Mit Bestätigung +``` + +--- + +## 🔹 Speichern & Beenden + +``` +:w Speichern +:q Beenden +:wq Speichern & Beenden +:x Speichern & Beenden +:q! Ohne Speichern beenden +``` + +--- + +## 🔹 Fenster & Tabs + +``` +:split Horizontal teilen +:vsplit Vertikal teilen +Ctrl+w w Zwischen Fenstern wechseln +:tabnew Neuer Tab +gt Nächster Tab +gT Vorheriger Tab +``` + +--- + +## 🔹 Nützliche Shortcuts + +``` +. Letzte Aktion wiederholen +>> Zeile einrücken +<< Zeile ausrücken +ciw Wort ändern +cc Zeile ändern +J Zeilen zusammenführen +``` + +--- + +## 🔹 Makros + +``` +qa Aufnahme in Register a starten +q Aufnahme stoppen +@a Makro a ausführen +@@ Letztes Makro wiederholen +``` + +--- + +## 🔹 Zahlen-Präfixe (Sehr wichtig!) + +Viele Befehle lassen sich multiplizieren: + +``` +3dd 3 Zeilen löschen +5w 5 Wörter vor +2yy 2 Zeilen kopieren +``` + +--- +# Zeilennummern aus- und anschalten + +--- + +## 🔹 Absolute Zeilennummern + +### Einschalten: + +```vim +:set number +``` + +### Ausschalten: + +```vim +:set nonumber +``` + +### Toggle: + +```vim +:set number! +``` + +--- + +## 🔹 Relative Zeilennummern + +### Einschalten: + +```vim +:set relativenumber +``` + +### Ausschalten: + +```vim +:set norelativenumber +``` + +### Toggle: + +```vim +:set relativenumber! +``` + +--- + +## 🔹 Absolute + Relative kombinieren (Sehr beliebt 🔥) + +Viele nutzen diese Kombination: + +```vim +:set number relativenumber +``` + +👉 Ergebnis: + +* Aktuelle Zeile = **absolute Nummer** +* Alle anderen Zeilen = **relative Nummern** + +Beispiel: + +``` + 8 + 2 + 1 + 10 ← aktuelle Zeile + 1 + 2 + 3 +``` + +Das ist perfekt für Bewegungen wie: + +``` +5j +3k +``` + +--- + +## 🔹 Dauerhaft aktivieren (.vimrc) + +In deiner `~/.vimrc`: + +```vim +set number +set relativenumber +``` + +--- + +## 🔹 Smart Toggle Mapping (Optional ⭐) + +Viele nutzen ein Keybinding: + +```vim +nnoremap n :set number! relativenumber! +``` + +Dann kannst du mit: + +``` +\ n +``` + +(beim Standard-`leader`) beide gleichzeitig toggeln. + +--- + + +# Block Aus- und Einkommentieren + +--- + +# 🔹 1️⃣ Rein mit Vim (ohne Plugin) + +## ✅ Ganze Zeilen im Visual Mode kommentieren + +### Schritt 1: Block markieren + +* `V` → Zeilenweise markieren +* `j / k` → Bereich wählen + +### Schritt 2: Kommentarzeichen einfügen + +Beispiel für `#`: + +```vim +:s/^/# / +``` + +Im Visual Mode einfach: + +```vim +:'<,'>s/^/# / +``` + +👉 Fügt `# ` am Anfang jeder markierten Zeile ein. + +--- + +## 🔹 Auskommentieren + +```vim +:'<,'>s/^# // +``` + +--- + +## 🔹 Noch schneller (ohne `:` tippen) + +Markieren mit `V`, dann: + +```vim +:s/^/# / +``` + +Vim setzt `'<,'>` automatisch. + +--- + +# 🔹 2️⃣ Noch effizienter: Visual Block Mode (Sehr elegant ⚡) + +Perfekt für feste Kommentarzeichen wie `#`, `//`, `--`. + +### Schritt 1 + +``` +Ctrl + v +``` + +### Schritt 2 + +Mit `j/k` mehrere Zeilen markieren (nur Spalte 0) + +### Schritt 3 + +``` +Shift + i +# +Esc +``` + +💥 Vim fügt das in alle markierten Zeilen ein. + +--- + +## 🔹 Entfernen mit Block Mode + +1. `Ctrl + v` +2. Erste 2 Zeichen (`# `) markieren +3. `d` + +--- + +# 🔹 3️⃣ Beste Lösung: Plugin (Empfohlen 🔥) + +Wenn du regelmäßig kommentierst → nimm ein Plugin. + +Sehr beliebt: + +* vim-commentary von Tim Pope + +### Installation (mit vim-plug): + +```vim +Plug 'tpope/vim-commentary' +``` + +### Nutzung: + +* `gcc` → aktuelle Zeile toggeln +* `gc` (im Visual Mode) → Block toggeln + +💎 Vorteil: + +* erkennt automatisch Kommentarzeichen je nach Dateityp +* funktioniert mit `//`, `#`, `--`, `/* */`, etc. + +--- + +# 🔹 4️⃣ Absolute Power-User Lösung (Ohne Plugin, aber smart) + +In `.vimrc`: + +```vim +vnoremap c :s/^/# / +vnoremap u :s/^# // +``` + +Dann: + +``` +\c → kommentieren +\u → auskommentieren +``` + +--- + +# 🔥 Meine Empfehlung + +| Wenn du... | Lösung | +| ----------------------------- | ----------------- | +| Nur selten kommentierst | Visual Block Mode | +| Viel programmierst | vim-commentary | +| Minimalistisch bleiben willst | eigenes Mapping | + +--- +# Verschiedenes +- `%`: zur nächsten Klammer +- `TOhtml`: HTML Export +- `:ls`: Buffer anzeigen -> `:b 3` den 3. Buffer öffnen +- `.` : letzte Aktion wiederholen +- `:e path/to/file` öffnet Datei, nur `:e` aktualisiert die geöffnete Datei, `:e!` verwirft dabei alle Änderungen \ No newline at end of file diff --git a/Computerkram/Linux/Wine.md b/Computerkram/Linux/Wine.md new file mode 100644 index 0000000..4b01c7f --- /dev/null +++ b/Computerkram/Linux/Wine.md @@ -0,0 +1,232 @@ +# Anleitung: Windows-Programme unter Linux mit **Wine** in einer eigenen Umgebung installieren + +Diese Anleitung zeigt dir, wie du **Windows-Programme unter Linux mithilfe von Wine** installierst – **pro Programm in einer eigenen isolierten Wine-Umgebung (Wineprefix)**. +Die Schritte funktionieren unter den meisten Linux-Distributionen (Ubuntu, Fedora, Arch, etc.). + +--- + +## ⭐ Grundbegriffe + +### **Wine** +Wine ist eine Kompatibilitätsschicht, die Windows-Programme unter Linux ausführen kann. + +### **Wineprefix** +Ein *Wineprefix* ist eine Art eigener Windows-Ordner (inkl. Registry, Laufwerke, DLLs). +Standard: `~/.wine` – wir nutzen jedoch **pro Programm einen eigenen Prefix**, z. B.: + +``` + +~/wineprefixes/MeinProgramm + +```` + +Das verhindert Konflikte zwischen Programmen. + +--- + +## 🛠️ Voraussetzungen + +### Wine & Winetricks installieren + +**Ubuntu/Debian** +```bash +sudo apt update +sudo apt install wine winetricks +```` + +**Fedora** + +```bash +sudo dnf install wine winetricks +``` + +**Arch Linux / Manjaro** + +```bash +sudo pacman -S wine winetricks +``` + +> Optional: Für bessere Kompatibilität empfiehlt sich _winehq-staging_. + +--- + +## 📁 1. Eigenen Wineprefix anlegen + +Ersetze `` durch den gewünschten Namen. + +```bash +export WINEPREFIX="$HOME/wineprefixes/" +wineboot --init +``` + +Ordnerstruktur anlegen (falls noch nicht vorhanden): + +```bash +mkdir -p "$HOME/wineprefixes" +``` + +--- + +## 🧩 2. Architektur festlegen (32- oder 64-bit) + +### 32-bit Prefix (für ältere Programme empfohlen) + +```bash +export WINEARCH=win32 +export WINEPREFIX="$HOME/wineprefixes/" +wineboot --init +``` + +### 64-bit Prefix + +```bash +export WINEARCH=win64 +export WINEPREFIX="$HOME/wineprefixes/" +wineboot --init +``` + +--- + +## 🧰 3. Prefix konfigurieren (optional) + +### Wine-Konfiguration starten + +```bash +export WINEPREFIX="$HOME/wineprefixes/" +winecfg +``` + +Hier kannst du z. B. einstellen: + +- Windows-Version (Win7, Win10, Win11) + +- Grafikoptionen + +- Audiotreiber + + +--- + +## 📦 4. Winetricks nutzen (DLLs, Fonts, Komponenten) + +Beispiel: .NET 4.8 & corefonts installieren: + +```bash +export WINEPREFIX="$HOME/wineprefixes/" +winetricks dotnet48 corefonts +``` + +Winetricks GUI öffnen: + +```bash +winetricks --gui +``` + +--- + +## 📥 5. Windows-Programm installieren + +Beispiel mit einer `setup.exe`: + +```bash +export WINEPREFIX="$HOME/wineprefixes/" +wine ~/Downloads/setup.exe +``` + +Installer wie gewohnt durchklicken. + +--- + +## ▶️ 6. Programm starten + +Wenn das Programm z. B. `Programm.exe` heißt: + +```bash +export WINEPREFIX="$HOME/wineprefixes/" +wine "$WINEPREFIX/drive_c/Program Files///Programm.exe" +``` + +--- + +## 📌 7. Starter (Desktop-Shortcut) erstellen + +Erstelle eine Datei: + +``` +~/.local/share/applications/.desktop +``` + +Inhalt: + +```desktop +[Desktop Entry] +Name= +Exec=env WINEPREFIX="/home/$USER/wineprefixes/" wine "C:/Program Files///Programm.exe" +Type=Application +Categories=Utility; +``` + +Datei ausführbar machen: + +```bash +chmod +x ~/.local/share/applications/.desktop +``` + +--- + +## 🧼 8. Prefix entfernen + +Wenn du das Programm löschen möchtest: + +```bash +rm -rf "$HOME/wineprefixes/" +``` + +--- + +## 🔍 Zusatz: Nützliche Tools + +### Wine Logs anzeigen + +```bash +WINEPREFIX="$HOME/wineprefixes/" wine Programm.exe &> log.txt +``` + +### Abhängigkeiten prüfen + +```bash +winetricks dlls list +``` + +--- + +## 📚 Tipps & Best Practices + +- **Jedes Programm bekommt seinen eigenen Prefix** → weniger Konflikte. + +- Für Spiele: **Lutris** oder **Bottles** nutzen. + +- Für Office-Software häufig nötig: `dotnet48`, `corefonts`, `vcrun2015`. + +- Falls ein Programm Probleme macht: + → WineHQ AppDB durchsuchen (Kompatibilitätsdatenbank). + + +--- + +## ✔️ Zusammenfassung + +1. Wine & Winetricks installieren + +2. Eigenen Prefix erstellen + +3. Architektur festlegen (32/64 bit) + +4. Wine konfigurieren + +5. Benötigte Komponenten via Winetricks installieren + +6. Setup des Programms ausführen + +7. Starter optional erstellen + diff --git a/Computerkram/Linux/mein fstab.md b/Computerkram/Linux/mein fstab.md new file mode 100644 index 0000000..df14302 --- /dev/null +++ b/Computerkram/Linux/mein fstab.md @@ -0,0 +1,106 @@ +# 🧭 Übersicht: `/etc/fstab` – Netzlaufwerke & SSHFS + +Diese Datei enthält Einträge für automatisch eingehängte Netzlaufwerke. +Wichtig: Teste Änderungen **immer** mit +```bash +sudo mount -a +``` +um Syntaxfehler zu erkennen, bevor du neustartest. +→ siehe [[fstab Grundlagen]] + +--- + +## 🗂️ NAS-Laufwerke via NFS + +```fstab +192.168.0.14:/volume1/Gemeinsam /mnt/nas/gemeinsam nfs nfsvers=3,rw,_netdev,noac,actimeo=0 0 0 +``` + +**Annahmen:** +- NAS-IP: `192.168.0.14` +- Freigabe (Quelle): `/volume1/Gemeinsam` +- Lokaler Mountpoint (Ziel): `/mnt/nas/gemeinsam` + +**Erläuterung der Optionen:** +- `nfsvers=3` → nutzt NFSv3 (älter, aber oft stabiler bei Synology) +- `rw` → Schreib-/Lesezugriff +- `_netdev` → mountet erst, wenn Netzwerk verfügbar ist +- `noac` → deaktiviert Client-Caching (nützlich bei Dateisynchronisierung, kann Performance senken) +- `actimeo=0` → setzt Cache-Timeout auf 0 (Dateiattribute werden immer neu gelesen) + +👉 siehe [[NFS unter Linux]] und [[NFS Mount Optionen]] + +💡 *Tipp:* +Bei neueren Systemen oder stabilen Netzwerken ist `nfsvers=4` meist die bessere Wahl. Beispiel: +```fstab +192.168.0.14:/volume1/Gemeinsam /mnt/nas/gemeinsam nfs nfsvers=4,rw,_netdev 0 0 +``` + +📦 **Benötigtes Paket (Debian/Ubuntu):** +```bash +sudo apt install nfs-common +``` +→ siehe [[NFS Client Installation]] + +--- + +## ☁️ HiDrive via SFTP (SSHFS) + +```fstab +mathias2784@sftp.hidrive.strato.com:/users/mathias2784 /mnt/hidrive fuse.sshfs defaults,_netdev,IdentityFile=/home/mathias/.ssh/id_ed25519,allow_other 0 0 +``` + +**Erläuterung der Optionen:** +- `fuse.sshfs` → nutzt das FUSE-Modul für SSHFS +- `_netdev` → warte auf Netzwerk +- `IdentityFile=...` → Pfad zum SSH-Key +- `allow_other` → erlaubt Zugriff auch für andere Nutzer (Achtung: [[SSHFS Sicherheit]]) + +👉 siehe [[SSHFS unter Linux]] und [[HiDrive Konfiguration]] + +💡 *Tipp:* +Füge optional `reconnect,ServerAliveInterval=15,ServerAliveCountMax=3` hinzu, damit die Verbindung stabil bleibt: +```fstab +mathias2784@sftp.hidrive.strato.com:/users/mathias2784 /mnt/hidrive fuse.sshfs _netdev,IdentityFile=/home/mathias/.ssh/id_ed25519,allow_other,reconnect,ServerAliveInterval=15,ServerAliveCountMax=3 0 0 +``` + +📦 **Benötigtes Paket (Debian/Ubuntu):** +```bash +sudo apt install sshfs +``` +→ siehe [[SSHFS Installation]] + +--- + +## 🖥️ "Schneiderserver" via SSHFS + +```fstab +root@schneiderserver.site:/root /mnt/strato_vm fuse.sshfs _netdev,IdentityFile=/home/mathias/.ssh/id_ed25519_strato_vm,allow_other 0 0 +``` + +**Optionen wie oben**, jedoch: +- Zugriff als `root` nur wenn zwingend notwendig (besser: Benutzer mit begrenzten Rechten) +- Key-File ggf. mit restriktiven Rechten (`chmod 600`) + +👉 siehe [[SSH Sicherheit]] und [[Root via SSH vermeiden]] + +📦 **Benötigtes Paket (Debian/Ubuntu):** +```bash +sudo apt install sshfs +``` + +--- + +## ✅ Allgemeine Hinweise + +- Testen: `sudo mount -a` +- Mounten einzelner Einträge: + ```bash + sudo mount /mnt/hidrive + ``` +- Logs prüfen bei Problemen: + ```bash + sudo journalctl -xe | grep sshfs + ``` + +Weitere Themen: [[fstab Optionen Übersicht]], [[Mount Fehlerbehebung]], [[Systemd Automounts]] \ No newline at end of file diff --git a/Computerkram/Linux/snapper.md b/Computerkram/Linux/snapper.md new file mode 100644 index 0000000..5298f8b --- /dev/null +++ b/Computerkram/Linux/snapper.md @@ -0,0 +1,479 @@ +# Snapper Anleitung für CachyOS - Detaillierte Version + +## Was ist Snapper? + +Snapper ist ein Tool für BTRFS-Dateisysteme, das automatisch Snapshots (Momentaufnahmen) erstellt. Diese Snapshots sind wie "Wiederherstellungspunkte" - sie speichern den Zustand deines Systems zu einem bestimmten Zeitpunkt, ohne zusätzlichen Speicherplatz für unveränderte Dateien zu verbrauchen. + +## Installation mit pacman + +```bash +# Hauptpakete installieren +sudo pacman -S snapper # Das eigentliche Snapper-Tool +sudo pacman -S snap-pac # Automatische Snapshots bei pacman-Operationen +sudo pacman -S snapper-gui-git # Grafische Benutzeroberfläche (optional) + +# Optional: Für GRUB-Integration (Boot-Menü mit Snapshots) +sudo pacman -S grub-btrfs # Zeigt Snapshots im GRUB-Boot-Menü an +``` + +## Grundkonfiguration verstehen + +### 1. Snapper-Konfiguration für Root erstellen + +```bash +# Falls bereits eine Konfiguration existiert, diese entfernen +sudo umount /.snapshots 2>/dev/null || true +sudo rm -rf /.snapshots + +# Neue Snapper-Konfiguration für das Root-Dateisystem erstellen +# Dies erstellt automatisch eine Konfigurationsdatei unter /etc/snapper/configs/root +sudo snapper -c root create-config / + +# Das automatisch erstellte .snapshots Verzeichnis ist ein normaler Ordner +# Wir brauchen aber ein BTRFS-Subvolume für bessere Performance +sudo btrfs subvolume delete /.snapshots +sudo mkdir /.snapshots + +# Subvolume in /etc/fstab eintragen (wird automatisch gemacht) +sudo mount -a +``` + +**Was passiert hier?** +- `-c root` = Konfigurationsname "root" +- `create-config /` = Erstelle Konfiguration für das Verzeichnis `/` +- Ein BTRFS-Subvolume ist effizienter als ein normaler Ordner für Snapshots + +### 2. Konfigurationsdatei im Detail + +```bash +sudo nano /etc/snapper/configs/root +``` + +**Wichtige Parameter erklärt:** + +```ini +# SUBVOLUME: Das zu überwachende Verzeichnis +SUBVOLUME="/" + +# FSTYPE: Dateisystemtyp (muss btrfs sein) +FSTYPE="btrfs" + +# ALLOW_USERS/ALLOW_GROUPS: Welche Benutzer dürfen Snapshots verwalten? +ALLOW_USERS="dein-benutzername" +ALLOW_GROUPS="wheel" + +# SYNC_ACL: Access Control Lists synchronisieren +SYNC_ACL="no" + +# === TIMELINE SNAPSHOTS (zeitbasierte automatische Snapshots) === + +# TIMELINE_CREATE: Sollen automatische zeitbasierte Snapshots erstellt werden? +TIMELINE_CREATE="yes" + +# TIMELINE_CLEANUP: Sollen alte Timeline-Snapshots automatisch gelöscht werden? +TIMELINE_CLEANUP="yes" + +# Wie viele Timeline-Snapshots sollen behalten werden? +TIMELINE_MIN_AGE="1800" # Mindestens 30 Minuten alt bevor Löschung möglich +TIMELINE_LIMIT_HOURLY="10" # Maximal 10 stündliche Snapshots +TIMELINE_LIMIT_DAILY="10" # Maximal 10 tägliche Snapshots +TIMELINE_LIMIT_WEEKLY="0" # Keine wöchentlichen Snapshots +TIMELINE_LIMIT_MONTHLY="10" # Maximal 10 monatliche Snapshots +TIMELINE_LIMIT_YEARLY="10" # Maximal 10 jährliche Snapshots + +# === NUMBER CLEANUP (Bereinigung nach Anzahl) === + +# NUMBER_CLEANUP: Snapshots nach Anzahl begrenzen? +NUMBER_CLEANUP="yes" + +# NUMBER_MIN_AGE: Snapshots müssen mindestens so alt sein (Sekunden) +NUMBER_MIN_AGE="1800" # 30 Minuten + +# NUMBER_LIMIT: Maximale Gesamtanzahl an Snapshots +NUMBER_LIMIT="50" + +# NUMBER_LIMIT_IMPORTANT: Wichtige Snapshots (pre/post) getrennt begrenzen +NUMBER_LIMIT_IMPORTANT="10" + +# === EMPTY CLEANUP (leere Snapshots löschen) === +EMPTY_PRE_POST_CLEANUP="yes" # Leere Pre/Post-Snapshot-Paare löschen +EMPTY_PRE_POST_MIN_AGE="1800" +``` + +**Was bedeuten die verschiedenen Snapshot-Typen?** +- **Timeline**: Automatisch nach Zeit erstellt (stündlich, täglich, etc.) +- **Pre/Post**: Vor und nach Systemänderungen (z.B. Package-Updates) +- **Single**: Einzelne manuelle Snapshots + +## Ein- und Ausgeschlossene Verzeichnisse verstehen + +### Automatisch eingeschlossene Verzeichnisse + +Standardmäßig wird **alles unter `/` gesnappt**, außer: + +```bash +# Diese Verzeichnisse werden NIEMALS gesnappt (hardcoded in Snapper): +/dev/* # Device-Dateien (virtuelle Dateien) +/proc/* # Process-Informationen (virtuelle Dateien) +/sys/* # System-Informationen (virtuelle Dateien) +/tmp/* # Temporäre Dateien +/run/* # Runtime-Daten +/mnt/* # Mount-Punkte +/media/* # Wechseldatenträger +``` + +### Zusätzliche Ausschlüsse konfigurieren + +**Option 1: Exclude-Patterns in der Hauptkonfiguration** + +```bash +sudo nano /etc/snapper/configs/root +``` + +Füge hinzu: +```ini +# EXCLUDE_PATTERNS: Glob-Patterns für auszuschließende Dateien/Ordner +EXCLUDE_PATTERNS="/var/cache/* /var/tmp/* /var/log/* /home/*/.cache/* /root/.cache/*" +``` + +**Option 2: Separate Filter-Datei (empfohlen)** + +```bash +# Filter-Datei erstellen +sudo mkdir -p /etc/snapper/filters +sudo nano /etc/snapper/filters/root.txt +``` + +Inhalt mit Erklärungen: +```bash +# Cache-Verzeichnisse (können jederzeit neu erstellt werden) +/var/cache/* +/home/*/.cache/* +/root/.cache/* + +# Temporäre Dateien +/var/tmp/* +/tmp/* + +# Log-Dateien (werden laufend überschrieben, Snapshots wenig sinnvoll) +/var/log/* + +# Browser-Profile (sehr große, häufig ändernde Dateien) +/home/*/.mozilla/firefox/*/Cache/* +/home/*/.config/google-chrome/Default/Cache/* + +# Papierkorb +/home/*/.local/share/Trash/* + +# Downloads (optional - je nach Bedarf) +# /home/*/Downloads/* + +# Virtuelle Maschinen (sehr groß) +/home/*/.local/share/libvirt/* +/var/lib/libvirt/* + +# Docker-Daten (sehr groß und dynamisch) +/var/lib/docker/* +``` + +Dann in der Hauptkonfiguration referenzieren: +```ini +# In /etc/snapper/configs/root hinzufügen: +EXCLUDE_FILE="/etc/snapper/filters/root.txt" +``` + +### Warum diese Ausschlüsse? + +- **Cache-Verzeichnisse**: Werden automatisch neu erstellt, verschwenden nur Platz +- **Log-Dateien**: Ändern sich ständig, Snapshots helfen nicht bei der Fehlersuche +- **Temporäre Dateien**: Per Definition temporär +- **Browser-Caches**: Riesig und unwichtig für System-Recovery +- **VM/Docker-Daten**: Sehr groß, haben eigene Backup-Strategien + +## Manuelle Snapshots erstellen + +### Einfache Snapshots + +```bash +# Einfacher Snapshot mit Beschreibung +sudo snapper -c root create -d "Vor Firefox-Installation" + +# Snapshot mit benutzerdefinierten Attributen +sudo snapper -c root create -d "Backup vor Kernel-Update" -u "important=yes" +``` + +### Pre/Post-Snapshot-Paare (empfohlen für größere Änderungen) + +```bash +# 1. PRE-Snapshot erstellen (vor der Änderung) +sudo snapper -c root create -t pre -p -d "Vor großem System-Update" +# Merke dir die Nummer! Z.B. "42" + +# 2. Deine Systemänderungen durchführen +sudo pacman -Syu + +# 3. POST-Snapshot erstellen (nach der Änderung) +sudo snapper -c root create -t post --pre-number 42 -d "Nach großem System-Update" +``` + +**Warum Pre/Post-Paare?** +- Snapper kann exakt die Unterschiede zwischen vorher/nachher zeigen +- Einfacheres Rollback nur der Änderungen +- Bessere Übersicht was sich geändert hat + +### Snapshots verwalten + +```bash +# Alle Snapshots auflisten +sudo snapper -c root list + +# Detaillierte Ansicht mit Größe +sudo snapper -c root list -t all + +# Informationen zu einem bestimmten Snapshot +sudo snapper -c root info 42 + +# Unterschiede zwischen zwei Snapshots anzeigen +sudo snapper -c root status 40..45 + +# Geänderte Dateien zwischen Snapshots zeigen +sudo snapper -c root diff 40..45 +``` + +## Automatisierung der Snapshot-Erstellung + +### 1. Timeline-Snapshots (zeitbasiert) + +```bash +# Systemd-Timer für stündliche Timeline-Snapshots aktivieren +sudo systemctl enable --now snapper-timeline.timer + +# Timer für automatische Bereinigung alter Snapshots aktivieren +sudo systemctl enable --now snapper-cleanup.timer + +# Status der Timer prüfen +systemctl status snapper-timeline.timer +systemctl status snapper-cleanup.timer + +# Nächste geplante Ausführung anzeigen +systemctl list-timers | grep snapper +``` + +**Was macht snapper-timeline.timer?** +- Läuft stündlich +- Erstellt automatisch Timeline-Snapshots basierend auf der Konfiguration +- Berücksichtigt die TIMELINE_LIMIT-Einstellungen + +**Was macht snapper-cleanup.timer?** +- Läuft täglich +- Löscht alte Snapshots basierend auf den Cleanup-Regeln +- Verhindert, dass das System mit Snapshots volläuft + +### 2. Automatische Snapshots bei Package-Updates + +Das Paket `snap-pac` erstellt automatisch Pre/Post-Snapshots bei jeder pacman-Operation. + +```bash +# Konfiguration von snap-pac anpassen +sudo nano /etc/snap-pac.ini +``` + +```ini +[DEFAULT] +# Maximale Länge der Snapshot-Beschreibung +desc_limit = 72 + +# Standard-Beschreibungen für automatische Snapshots +pre_description = pacman pre snapshot +post_description = pacman post snapshot + +# Soll snap-pac auch bei AUR-Helper-Updates Snapshots erstellen? +aur_helper = yay,paru,pikaur + +[root] +# Snapshots für das root-Subvolume aktivieren +snapshot = yes + +# Welche Cleanup-Strategie verwenden? +cleanup = number + +# Soll snap-pac auch bei normalen pacman-Operationen (nicht nur -S) Snapshots erstellen? +important = yes +``` + +**Was passiert jetzt?** +- Bei jedem `sudo pacman -S paket` → automatisches Pre/Post-Snapshot-Paar +- Bei `yay -S aur-paket` → ebenfalls Snapshots (wenn konfiguriert) +- Bei `sudo pacman -R paket` → ebenfalls Snapshots + +### 3. GRUB-Integration für Boot-Menü + +```bash +# GRUB-Btrfs-Daemon aktivieren (überwacht Snapshot-Änderungen) +sudo systemctl enable --now grub-btrfsd + +# Initramfs-Hook für Snapshot-Booting hinzufügen +sudo nano /etc/mkinitcpio.conf +``` + +In der HOOKS-Zeile hinzufügen: +```bash +HOOKS=(base udev autodetect modconf kms keyboard keymap consolefont block filesystems grub-btrfs-overlayfs fsck) +``` + +```bash +# Initramfs neu generieren +sudo mkinitcpio -P + +# GRUB-Konfiguration aktualisieren +sudo grub-mkconfig -o /boot/grub/grub.cfg +``` + +**Was bringt das?** +- Im GRUB-Boot-Menü erscheint ein neuer Eintrag "Snapshots for GNU/Linux" +- Du kannst direkt von einem Snapshot booten ohne das System zu ändern +- Perfekt um zu testen, ob ein älterer Zustand das Problem löst + +## Snapshots wiederherstellen + +### 1. Einzelne Dateien wiederherstellen + +```bash +# Snapshot mounten (macht ihn als Verzeichnis verfügbar) +sudo snapper -c root mount 42 + +# Jetzt ist der Snapshot verfügbar unter: +# /.snapshots/42/snapshot/ + +# Beispiel: Konfigurationsdatei wiederherstellen +sudo cp /.snapshots/42/snapshot/etc/fstab /etc/fstab + +# Beispiel: Ganzes Verzeichnis wiederherstellen +sudo cp -r /.snapshots/42/snapshot/etc/NetworkManager/ /etc/ + +# Snapshot wieder unmounten (Speicher freigeben) +sudo snapper -c root umount 42 +``` + +### 2. Änderungen zwischen Snapshots rückgängig machen + +```bash +# Zeige was sich zwischen zwei Snapshots geändert hat +sudo snapper -c root status 40..45 + +# Mache alle Änderungen zwischen den Snapshots rückgängig +sudo snapper -c root undochange 40..45 + +# Alternativ: Rollback zu einem bestimmten Snapshot +sudo snapper -c root rollback 42 +``` + +**Vorsicht bei undochange:** +- Überschreibt aktuelle Dateien! +- Erstelle vorher einen aktuellen Snapshot als Backup +- Teste erst in einer nicht-kritischen Umgebung + +### 3. Komplettes System-Rollback (für Experten) + +```bash +# ACHTUNG: Dies überschreibt dein aktuelles System! +# Erstelle erst einen Snapshot des aktuellen Zustands +sudo snapper -c root create -d "Vor Rollback - Notfall-Backup" + +# Zeige verfügbare Snapshots +sudo snapper -c root list + +# Rollback zu Snapshot (z.B. Nummer 42) +sudo btrfs subvolume snapshot /.snapshots/42/snapshot / +``` + +### 4. Boot von Snapshot über GRUB + +Wenn grub-btrfs installiert ist: + +1. **Computer neu starten** +2. **Im GRUB-Menü**: "Snapshots for GNU/Linux" wählen +3. **Snapshot auswählen**: Den gewünschten Snapshot aus der Liste wählen +4. **System startet** vom gewählten Snapshot (read-only) +5. **Wenn alles funktioniert**: `sudo snapper rollback` um permanent zu wechseln + +## Überwachung und Wartung + +### Speicherplatz überwachen + +```bash +# BTRFS-Dateisystem-Nutzung anzeigen +sudo btrfs filesystem usage / + +# Größe aller Snapshots anzeigen +sudo btrfs subvolume list / | grep snapshots + +# Detaillierte Snapshot-Größen +for snap in $(sudo snapper -c root list | tail -n +3 | awk '{print $1}'); do + if [ "$snap" != "0" ]; then + size=$(sudo btrfs subvolume show "/.snapshots/$snap/snapshot" 2>/dev/null | grep -E "^\s*Gen:" | wc -l) + echo "Snapshot $snap: Exists" + fi +done +``` + +### Automatische Bereinigung konfigurieren + +```bash +# Manuelle Bereinigung ausführen +sudo snapper -c root cleanup number # Nach Anzahl-Regeln +sudo snapper -c root cleanup timeline # Nach Zeit-Regeln + +# Bereinigung-Logs anzeigen +journalctl -u snapper-cleanup.service +``` + +## Fehlerbehandlung und Tipps + +### Häufige Probleme + +**Problem**: `/.snapshots` ist ein normaler Ordner, kein Subvolume +```bash +# Lösung: +sudo umount /.snapshots +sudo rm -rf /.snapshots +sudo btrfs subvolume create /.snapshots +sudo systemctl restart snapper-timeline.timer +``` + +**Problem**: Snapshots verbrauchen zu viel Speicher +```bash +# Lösung: Bereinigungsregeln anpassen +sudo nano /etc/snapper/configs/root +# NUMBER_LIMIT reduzieren (z.B. auf 20) +# Mehr Ausschlüsse hinzufügen +``` + +**Problem**: Automatische Snapshots funktionieren nicht +```bash +# Debugging: +systemctl status snapper-timeline.timer +journalctl -u snapper-timeline.service +sudo snapper -c root create -d "Test" # Manuell testen +``` + +### Best Practices + +1. **Vor großen Änderungen**: Immer manuelles Pre/Post-Snapshot-Paar +2. **Regelmäßige Kontrolle**: `sudo snapper list` alle paar Tage prüfen +3. **Speicherplatz überwachen**: Bei >80% Festplattenbelegung Snapshots reduzieren +4. **Test-Rollbacks**: Erst in VM oder Testsystem ausprobieren +5. **Backup-Strategie**: Snapper ersetzt keine externe Datensicherung! +6. **Wichtige Daten**: Separat in `/home` mit eigenem Snapshot-Schema verwalten + +### Erweiterte Konfiguration für /home + +```bash +# Separate Snapshot-Konfiguration für Home-Verzeichnis +sudo snapper -c home create-config /home + +# Andere Bereinigungsregeln für /home (mehr Snapshots, da wichtiger) +sudo nano /etc/snapper/configs/home +``` + +Diese detaillierte Anleitung sollte dir ein vollständiges Verständnis von Snapper und dessen Konfiguration geben! \ No newline at end of file diff --git a/Computerkram/Navidrome Rescan.md b/Computerkram/Navidrome Rescan.md new file mode 100644 index 0000000..7a626f4 --- /dev/null +++ b/Computerkram/Navidrome Rescan.md @@ -0,0 +1,84 @@ +[[Navidrome]] +## 🧩 **Option 1: Über die Web-Oberfläche** + +Wenn du nur die Bibliothek neu scannen willst: + +1. Melde dich als **Admin** in der Weboberfläche an. + +2. Gehe zu **Settings → Admin → Rescan Library** (oder „Bibliothek neu scannen“). + +3. Wähle **„Full Rescan“** (Vollständiger Scan) aus. + + +Das ist der einfachste Weg — aber wenn du den Vorgang **per Shell oder Skript** auslösen willst, siehe Option 2 oder 3. + +--- + +## 🐳 **Option 2: Über die Docker Shell** + +Wenn du direkten Zugriff auf den Container hast: + +```bash +docker exec -it navidrome rescan --force +``` + +🔹 `` ersetzt du durch den tatsächlichen Namen deines Containers, z. B. `navidrome`. +🔹 Der Parameter `--force` erzwingt eine vollständige Neuindizierung (nicht nur eine inkrementelle). + +Beispiel: + +```bash +docker exec -it navidrome navidrome rescan --force +``` + +Falls `navidrome` nicht im `PATH` ist (z. B. je nach Image): + +```bash +docker exec -it navidrome /app/navidrome rescan --force +``` + +--- + +## ⚙️ **Option 3: Durch Neustart mit Umgebungsvariable** + +Wenn du den Container neu startest und gleich beim Start eine Neuindizierung erzwingen willst, kannst du temporär folgende Umgebungsvariable setzen: + +```bash +docker run -d \ + -e ND_SCAN_ON_STARTUP=true \ + -e ND_SCAN_FORCED=true \ + ... + --name navidrome \ + deluan/navidrome:latest +``` + +Oder, wenn du `docker-compose` nutzt: + +```yaml +environment: + - ND_SCAN_ON_STARTUP=true + - ND_SCAN_FORCED=true +``` + +Dann einmal: + +```bash +docker compose restart navidrome +``` + +Das löst bei jedem Start eine **vollständige Neuindizierung** aus. + +--- + +## 🧠 **Zusatzinfos** + +- `navidrome rescan` akzeptiert auch `--quiet` (ohne Logausgabe). + +- Der Fortschritt erscheint in den Logs: + + ```bash + docker logs -f navidrome + ``` + +- Die Indizierung kann bei großen Bibliotheken einige Zeit dauern. + \ No newline at end of file diff --git a/Computerkram/Open WebUI.md b/Computerkram/Open WebUI.md new file mode 100644 index 0000000..3bb5441 --- /dev/null +++ b/Computerkram/Open WebUI.md @@ -0,0 +1,207 @@ + + +**Open WebUI is an [extensible](https://docs.openwebui.com/features/plugin/), feature-rich, and user-friendly self-hosted AI platform designed to operate entirely offline.** It supports various LLM runners like **Ollama** and **OpenAI-compatible APIs**, with **built-in inference engine** for RAG, making it a **powerful AI deployment solution**. + +Passionate about open-source AI? [Join our team →](https://careers.openwebui.com/) + +![GitHub stars](https://img.shields.io/github/stars/open-webui/open-webui?style=social) ![GitHub forks](https://img.shields.io/github/forks/open-webui/open-webui?style=social) ![GitHub watchers](https://img.shields.io/github/watchers/open-webui/open-webui?style=social) ![GitHub repo size](https://img.shields.io/github/repo-size/open-webui/open-webui) ![GitHub language count](https://img.shields.io/github/languages/count/open-webui/open-webui) ![GitHub top language](https://img.shields.io/github/languages/top/open-webui/open-webui) ![GitHub last commit](https://img.shields.io/github/last-commit/open-webui/open-webui?color=red) [![Discord](https://img.shields.io/badge/Discord-Open_WebUI-blue?logo=discord&logoColor=white)](https://discord.gg/5rJgQTnV4s) [![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/tjbck) + +![Open WebUI Demo](https://docs.openwebui.com/assets/images/demo-d3952c8561c4808c1d447fc061c71174.gif) + +tip + +**Looking for an [Enterprise Plan](https://docs.openwebui.com/enterprise)?** — **[Speak with Our Sales Team Today!](mailto:sales@openwebui.com)** + +Get **enhanced capabilities**, including **custom theming and branding**, **Service Level Agreement (SLA) support**, **Long-Term Support (LTS) versions**, and **more!** + +## Quick Start with [[Docker]] 🐳 + +info + +**WebSocket** support is required for Open WebUI to function correctly. Ensure that your network configuration allows WebSocket connections. + +**If Ollama is on your computer**, use this command: + +``` +docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main +``` + +**To run Open WebUI with Nvidia GPU support**, use this command: + +``` +docker run -d -p 3000:8080 --gpus all --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:cuda +``` + +For environments with limited storage or bandwidth, Open WebUI offers slim image variants that exclude pre-bundled models. These images are significantly smaller but download required models on first use: + +``` +docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main-slim +``` + +### Open WebUI Bundled with Ollama + +This installation method uses a single container image that bundles Open WebUI with Ollama, allowing for a streamlined setup via a single command. Choose the appropriate command based on your hardware setup: + +- **With GPU Support**: Utilize GPU resources by running the following command: + + ``` + docker run -d -p 3000:8080 --gpus=all -v ollama:/root/.ollama -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:ollama + ``` + + +- **For CPU Only**: If you're not using a GPU, use this command instead: + + ``` + docker run -d -p 3000:8080 -v ollama:/root/.ollama -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:ollama + ``` + + +Both commands facilitate a built-in, hassle-free installation of both Open WebUI and Ollama, ensuring that you can get everything up and running swiftly. + +After installation, you can access Open WebUI at [http://localhost:3000](http://localhost:3000). Enjoy! 😄 + +### Using the Dev Branch 🌙 + +warning + +The `:dev` branch contains the latest unstable features and changes. Use it at your own risk as it may have bugs or incomplete features. + +If you want to try out the latest bleeding-edge features and are okay with occasional instability, you can use the `:dev` tag like this: + +``` +docker run -d -p 3000:8080 -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:dev +``` + +For the slim variant of the dev branch: + +``` +docker run -d -p 3000:8080 -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:dev-slim +``` + +### Updating Open WebUI + +To update Open WebUI container easily, follow these steps: + +#### Manual Update + +Use [Watchtower](https://containrrr.dev/watchtower) to update your Docker container manually: + +``` +docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower --run-once open-webui +``` + +#### Automatic Updates + +Keep your container updated automatically every 5 minutes: + +``` +docker run -d --name watchtower --restart unless-stopped -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower --interval 300 open-webui +``` + +🔧 **Note**: Replace `open-webui` with your container name if it's different. + +## Manual Installation + +info + +### Platform Compatibility + +Open WebUI works on macOS, [[Linux]] (x86_64 and ARM64, including Raspberry Pi and other ARM boards), and Windows. + +There are two main ways to install and run Open WebUI: using the `uv` runtime manager or Python's `pip`. While both methods are effective, **we strongly recommend using `uv`** as it simplifies environment management and minimizes potential conflicts. + +### Installation with `uv` (Recommended) + +The `uv` runtime manager ensures seamless Python environment management for applications like Open WebUI. Follow these steps to get started: + +#### 1. Install `uv` + +Pick the appropriate installation command for your operating system: + +- **macOS/Linux**: + + ``` + curl -LsSf https://astral.sh/uv/install.sh | sh + ``` + + +- **Windows**: + + ``` + powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" + ``` + + +#### 2. Run Open WebUI + +Once `uv` is installed, running Open WebUI is a breeze. Use the command below, ensuring to set the `DATA_DIR` environment variable to avoid data loss. Example paths are provided for each platform: + +- **macOS/Linux**: + + ``` + DATA_DIR=~/.open-webui uvx --python 3.11 open-webui@latest serve + ``` + + +- **Windows**: + + ``` + $env:DATA_DIR="C:\open-webui\data"; uvx --python 3.11 open-webui@latest serve + ``` + + +note + +**For PostgreSQL Support:** + +The default installation now uses a slimmed-down package. If you need **PostgreSQL support**, install with all optional dependencies: + +``` +pip install open-webui[all] +``` + +### Installation with `pip` + +For users installing Open WebUI with [[Python]]'s package manager `pip`, **it is strongly recommended to use Python runtime managers like `uv` or `conda`**. These tools help manage Python environments effectively and avoid conflicts. + +Python 3.11 is the development environment. Python 3.12 seems to work but has not been thoroughly tested. Python 3.13 is entirely untested and some dependencies do not work with Python 3.13 yet—**use at your own risk**. + +1. **Install Open WebUI**: + + Open your terminal and run the following command: + + ``` + pip install open-webui + ``` + + +- **Start Open WebUI**: + + Once installed, start the server using: + + ``` + open-webui serve + ``` + + +### Updating Open WebUI + +To update to the latest version, simply run: + +``` +pip install --upgrade open-webui +``` + +This method installs all necessary dependencies and starts Open WebUI, allowing for a simple and efficient setup. After installation, you can access Open WebUI at [http://localhost:8080](http://localhost:8080). Enjoy! 😄 + +## Other Installation Methods + +We offer various installation alternatives, including non-Docker native installation methods, Docker Compose, Kustomize, and Helm. Visit our [Open WebUI Documentation](https://docs.openwebui.com/getting-started/) or join our [Discord community](https://discord.gg/5rJgQTnV4s) for comprehensive guidance. + +Continue with the full [getting started guide](https://docs.openwebui.com/getting-started). + +### Desktop App + +We also have an **experimental** desktop app, which is actively a **work in progress (WIP)**. While it offers a convenient way to run Open WebUI natively on your system without Docker or manual setup, it is **not yet stable**. + +👉 For stability and production use, we strongly recommend installing via **Docker** or **Python (`uv` or `pip`)**. \ No newline at end of file diff --git a/Computerkram/Python/argpase.md b/Computerkram/Python/argpase.md new file mode 100644 index 0000000..49a4864 --- /dev/null +++ b/Computerkram/Python/argpase.md @@ -0,0 +1,385 @@ +# argpase + +--- + +## 1. Grundidee von `argparse` + +`argparse` ist das Standardmodul in Python, um Kommandozeilen-Argumente zu definieren, zu parsen und automatisch Hilfe-/Usage-Texte zu erzeugen. + +Minimalbeispiel: + +```python +import argparse + +parser = argparse.ArgumentParser(description="Ein kleines Beispiel-CLI") +parser.add_argument("datei", help="Pfad zur Eingabedatei") +args = parser.parse_args() + +print(args.datei) +``` + +Aufruf: + +```bash +python script.py meine_datei.txt +``` + +--- + +## 2. Argumente definieren: `ArgumentParser.add_argument` + +### 2.1 Positionsargumente + +- Werden ohne führende `-` oder `--` angegeben. +- Reihenfolge ist relevant. + +```python +parser.add_argument("quelle", help="Quellpfad") +parser.add_argument("ziel", help="Zielpfad") +``` + +Aufruf: + +```bash +python script.py input.txt output.txt +``` + +Use-Case: + +- Pflichtwerte, die immer gebraucht werden (z.B. Eingabe- und Ausgabedatei). + +--- + +### 2.2 Optionale Argumente (Flags / Optionen) + +- Beginnen mit `-` bzw. `--`. +- Reihenfolge ist egal. +- Können Standardwerte haben. + +```python +parser.add_argument( + "-v", "--verbose", + action="store_true", + help="Ausführliche Ausgabe aktivieren" +) + +parser.add_argument( + "-n", "--anzahl", + type=int, + default=10, + help="Anzahl der Elemente (Standard: 10)" +) +``` + +Aufruf: + +```bash +python script.py input.txt --verbose --anzahl 5 +# oder kurz: +python script.py input.txt -v -n 5 +``` + +Use-Case: + +- Konfiguration, optionales Verhalten, Debug/Verbose-Flags, Parameter mit Default. + +--- + +## 3. Wichtige Parameter von `add_argument` + +### 3.1 `name` / `flags` + +- Beispiel: + - Positional: `"datei"` + - Optional: `"-v", "--verbose"` + +```python +parser.add_argument("datei") +parser.add_argument("-v", "--verbose") +``` + +--- + +### 3.2 `type` + +- Convertiert Eingabe in Typ. +- Validiert automatisch (bei falschem Typ Fehler + Hilfe). + +```python +parser.add_argument("--port", type=int, default=8080) +parser.add_argument("--faktor", type=float) +``` + +Use-Case: + +- Numerische Werte, Pfade, eigene Typen (z.B. `Path` aus `pathlib`). + +--- + +### 3.3 `default` + +- Standardwert, wenn Argument nicht übergeben wird. + +```python +parser.add_argument("--log-level", default="INFO") +``` + +Use-Case: + +- Sinnvolle Defaults, um CLI kompakt zu halten. + +--- + +### 3.4 `required` + +- Macht optionale Argumente zwingend erforderlich. + +```python +parser.add_argument("--config", required=True) +``` + +Use-Case: + +- Flags/Optionen, die zwingend gesetzt werden müssen (z.B. API-Key, Konfigdatei). + +--- + +### 3.5 `help` + +- Beschreibung für die `--help`-Ausgabe. + +```python +parser.add_argument("--mode", help="Betriebsmodus: fast oder safe") +``` + +Use-Case: + +- Dokumentation der Optionen (sehr wichtig für Benutzerfreundlichkeit). + +--- + +### 3.6 `choices` + +- Schränkt erlaubte Werte ein. + +```python +parser.add_argument( + "--mode", + choices=["fast", "safe"], + default="safe", + help="fast = schneller, safe = sicherer" +) +``` + +Use-Case: + +- Enum-ähnliche Optionen (z.B. `debug/info/warn/error`, `json/text`). + +--- + +### 3.7 `action` + +Steuert, was passiert, wenn das Argument gesetzt wird. + +Häufige Actions: + +1. `store` (Standard) + Speichert den Wert (z.B. `--port 8000` → `args.port = 8000`). +2. `store_true` / `store_false` + Boolean-Flag, das `True`/`False` setzt. + + ```python + parser.add_argument("-v", "--verbose", action="store_true") + ``` +3. `append` + Fügt mehrere Werte in eine Liste ein. + + ```python + parser.add_argument( + "-t", "--tag", + action="append", + help="Kann mehrfach verwendet werden" + ) + # Aufruf: --tag a --tag b -> args.tag = ["a", "b"] + ``` +4. `count` + Zählt, wie oft ein Flag verwendet wurde. + + ```python + parser.add_argument( + "-v", "--verbose", + action="count", + default=0, + help="Mehrfach verwenden für mehr Details" + ) + # -v -> 1, -vv -> 2 ... + ``` + +Use-Case: + +- Flags (bool), Mehrfachangaben (Listen), Verbosity-Level etc. + +--- + +### 3.8 `nargs` + +Gibt an, wie viele Werte zu einem Argument gehören. + +Typische Varianten: + +- `nargs=1` → eine Liste mit einem Element +- `nargs=2` → genau 2 Werte +- `nargs="+"` → mindestens ein Wert +- `nargs="*"` → beliebig viele (auch 0) + +```python +parser.add_argument("dateien", nargs="+", help="Eine oder mehrere Dateien") +parser.add_argument("--koordinaten", nargs=2, type=float, help="x y") +``` + +Use-Case: + +- Mehrere Dateien, Koordinaten, Listen von Werten. + +--- + +### 3.9 `metavar` + +- Steuert, wie das Argument im Help-Text angezeigt wird. + +```python +parser.add_argument( + "--output", + metavar="DATEI", + help="Ausgabedatei" +) +``` + +Use-Case: + +- Schöner formatierte Hilfe (statt generischer Namen). + +--- + +### 3.10 `dest` + +- Name des Attributes in `args`. + +```python +parser.add_argument("-o", "--output", dest="ausgabedatei") +# args.ausgabedatei +``` + +Use-Case: + +- Lesbare/konfliktfreie Python-Bezeichner, wenn CLI-Namen nicht ideal sind. + +--- + +## 4. Subkommandos: `subparsers` + +Für CLI-Tools mit mehreren Befehlen (ähnlich `git commit`, `git status`). + +```python +import argparse + +parser = argparse.ArgumentParser(prog="tool") +subparsers = parser.add_subparsers(dest="command", required=True) + +# Subkommando: "run" +run_parser = subparsers.add_parser("run", help="Job ausführen") +run_parser.add_argument("job_id", type=int) + +# Subkommando: "list" +list_parser = subparsers.add_parser("list", help="Jobs auflisten") +list_parser.add_argument("--status", choices=["open", "done"]) + +args = parser.parse_args() + +if args.command == "run": + print(f"Starte Job {args.job_id}") +elif args.command == "list": + print(f"Liste Jobs mit Status {args.status}") +``` + +Aufrufe: + +```bash +tool run 42 +tool list --status open +``` + +Use-Case: + +- Umfangreiche Tools mit verschiedenen Befehlen (z.B. Admin-Tools, Deployment-CLI). + +--- + +## 5. Automatische Hilfe und Usage + +`argparse` erzeugt automatisch `-h` / `--help`: + +```bash +python script.py --help +``` + +Du bekommst: + +- Beschreibung (`description`) +- Liste aller Argumente +- Default-Werte (wenn konfiguriert) +- Subkommandos (falls vorhanden) + +Beispiel: + +```python +parser = argparse.ArgumentParser( + description="Konvertiert Dateien in andere Formate." +) +``` + +--- + +## 6. Minimaler „Best-Practice“-Skeleton + +```python +import argparse + +def parse_args(): + parser = argparse.ArgumentParser( + description="Beispiel-Tool für argparse" + ) + + # Positionsargumente + parser.add_argument("eingabe", help="Eingabedatei") + + # Optionale Argumente + parser.add_argument( + "-o", "--output", + help="Ausgabedatei (Standard: stdout)" + ) + parser.add_argument( + "-v", "--verbose", + action="store_true", + help="Ausführliche Ausgabe" + ) + parser.add_argument( + "--mode", + choices=["fast", "safe"], + default="safe", + help="Verarbeitungsmodus (Standard: safe)" + ) + + return parser.parse_args() + +def main(): + args = parse_args() + if args.verbose: + print(f"Starte in Modus {args.mode} mit Eingabe {args.eingabe}") + # weitere Logik… + +if __name__ == "__main__": + main() +``` + +--- \ No newline at end of file diff --git a/Computerkram/Webseiten, selbstgehostet/Build a Scalable Flask Web Project From Scratch (Real Python).md b/Computerkram/Webseiten, selbstgehostet/Build a Scalable Flask Web Project From Scratch (Real Python).md new file mode 100644 index 0000000..976b08b --- /dev/null +++ b/Computerkram/Webseiten, selbstgehostet/Build a Scalable Flask Web Project From Scratch (Real Python).md @@ -0,0 +1,342 @@ +Flask is a powerful and flexible micro web framework for Python, ideal for both small and large web projects. It provides a straightforward way to get a web application up and running, with all the features that you need to get started. + +Over the course of this tutorial, you’ll explore the process of creating a boilerplate for a Flask web project. This boilerplate will serve as a great starting point for any scalable Flask web app that you wish to develop in the future, from basic web pages to complex web applications. + +**In this tutorial, you’ll learn how to:** + +- Set up a **Flask project** +- Create a `"Hello, World!"` **Flask app** +- Add **multiple pages** with blueprints +- Leverage **Jinja templates** +- Store **static files** + +At the end of this tutorial, you’ll have created a working Flask web application that you can use to bootstrap your future Flask projects. + +**Get Your Code:** [Click here to download the free source code](https://realpython.com/bonus/flask-project-code/) that shows you how to build a Flask project boilerplate. + +==**Take the Quiz:**== Test your knowledge with our interactive “Build a Scalable Flask Web Project From Scratch” quiz. You’ll receive a score upon completion to help you track your learning progress: + +--- + +[ + +![Build a Scalable Flask Web Project From Scratch](https://files.realpython.com/media/UPDATE-Python-Web-Applications-with-Flask-1_Watermarked.3e384f2e53cf.jpg) + + + +](https://realpython.com/quizzes/flask-project/) + +**Interactive Quiz** + +[Build a Scalable Flask Web Project From Scratch](https://realpython.com/quizzes/flask-project/) + +Test your knowledge of Flask basics, blueprints, project structure, Jinja templates, static files, and setup steps. + +## Prerequisites[](https://realpython.com/flask-project/#prerequisites "Permanent link") + +You don’t need any previous knowledge of Flask to complete this project. If you want to learn more about the topics that you encounter in this tutorial, then you’ll find links to resources along the way. + +However, you should be comfortable using the [terminal](https://realpython.com/terminal-commands/) and have [basic knowledge](https://realpython.com/products/python-basics-book/) of Python. Although it helps to know about [virtual environments](https://realpython.com/python-virtual-environments-a-primer/) and [`pip`](https://realpython.com/what-is-pip/), you’ll learn how to set everything up as you work through the tutorial. + +[Remove ads](https://realpython.com/account/join/) + +## Project Overview[](https://realpython.com/flask-project/#project-overview "Permanent link") + +In this tutorial, you’ll start building a Flask project, which could become a public message board at some point. Here’s what the project will look at the end of this tutorial: + +You create a basic Flask project with two pages that inherit content and style from a parent template. + +The Flask project that you’ll build in this tutorial will be very generic. That way, it’s the perfect base for any of your future projects. For example, maybe you’ll want to [add a database](https://realpython.com/flask-database/) or implement [logging and notification messages](https://realpython.com/flask-logging-messages/). + +## Get Started[](https://realpython.com/flask-project/#get-started "Permanent link") + +In this section, you’ll prepare the development environment for your Flask project. First, you’ll create a **virtual environment** and install all the **dependencies** that you need for your project. + +### Create a Virtual Environment[](https://realpython.com/flask-project/#create-a-virtual-environment "Permanent link") + +In this section, you’ll build your project structure. You can name the root folder of your project any way you like. For example, you could name it `rp_flask_board/` if your ultimate goal is to create a message board. If you have another project in mind, then feel free to name your folder accordingly. Create your folder and navigate into it: + +`$ mkdir rp_flask_board $ cd rp_flask_board` + +In this case, you name the root folder of your project `rp_flask_board/`. The files and folders that you create over the course of this series will be located in either this folder or its subfolders. + +After you navigate to the project folder, it’s a good idea to create and activate a [virtual environment](https://realpython.com/python-virtual-environments-a-primer/). That way, you’re installing any project dependencies not system-wide but only in your project’s virtual environment. + +Select your **operating system** below and use your platform-specific command to set up a virtual environment: + +- [Windows](https://realpython.com/flask-project/#windows-1) +- [Linux + macOS](https://realpython.com/flask-project/#linux-macos-1) + +`$ python -m venv venv $ source venv/bin/activate (venv) $` + +With the commands shown above, you create and activate a virtual environment named `venv` by using Python’s built-in `venv` module. The parenthesized `(venv)` in front of the prompt indicates that you’ve successfully activated the virtual environment. + +### Add Dependencies[](https://realpython.com/flask-project/#add-dependencies "Permanent link") + +After you’ve created and activated your virtual environment, it’s time to install **Flask** with [`pip`](https://realpython.com/what-is-pip/): + +`(venv) $ python -m pip install Flask` + +The Flask **micro web framework** is the only direct dependency that your project requires. This is good news because that means that you can now start coding your Flask project. + +[Remove ads](https://realpython.com/account/join/) + +## Initiate Your Flask Project[](https://realpython.com/flask-project/#initiate-your-flask-project "Permanent link") + +In this section, you’ll spin up a **development server** and display `"Hello, World!"` in the browser with just a few lines of code. Then, you’ll expand your project structure to prepare a scalable Flask web application. + +### Run the Flask Development Server[](https://realpython.com/flask-project/#run-the-flask-development-server "Permanent link") + +A Flask project can be as basic as one Python file, which is commonly named `app.py`. Give it a try by creating `app.py` in `rp_flask_board/` and adding the following content: + +`app.py` + +`from flask import Flask app = Flask(__name__) @app.route("/") def home(): return "Hello, World!" if __name__ == "__main__": app.run(host="0.0.0.0", port=8000, debug=True)` + +You import the `Flask` class, giving the application access to the Flask functionality. You then create a Flask application instance named `app`. Next, you connect the URL route `"/"` to the `home()` function by [decorating](https://realpython.com/primer-on-python-decorators/) it with `@app.route("/")`. Functions like these are commonly referred to as **views** in Flask. In this case, the `home` view returns a `"Hello, World!"` string that the browser can display. + +**Note:** Flask’s development server defaults to port `5000`. But on newer macOS versions, the macOS [AirPlay receiver](https://en.wikipedia.org/wiki/AirPlay#Receivers) uses this port. Above, you’ve changed the port of your Flask app with `port=8000`. If you want, you can [change the AirPlay receiver preferences on your Mac](https://support.apple.com/guide/mac-help/change-airplay-receiver-preferences-on-mac-mchl15c9e4b5/mac) instead. + +With the Python virtual environment active, you can run your application with this command in the directory containing the `app.py` file: + +`(venv) $ python app.py` + +When you run `app.py`, a web server will start on port 8000. If you open a browser and navigate to `http://localhost:8000`, then you should see _Hello, World!_ displayed: + +[![Hello World Flask App](https://files.realpython.com/media/helloworld.c5d1d5655deb.png)](https://files.realpython.com/media/helloworld.c5d1d5655deb.png) + +Congratulations, your web server is running! You can stop the development server by pressing Ctrl+C in your terminal. + +Your current project structure is great for starting a Flask project. However, if you want to work on bigger projects, this structure can be limiting because you’d need to add more and more code to `app.py`. Instead, you’ll adjust the structure a bit to create a more scalable Flask project. + +### Transform Your Project Into a Package[](https://realpython.com/flask-project/#transform-your-project-into-a-package "Permanent link") + +[Packages](https://realpython.com/python-modules-packages/) are useful for structuring Python code into logical groupings for large programs. Because your web project can grow large, too, transforming your project into a package makes sense. Since you’re just at the start of the project, your to-do list to create the package has only three tasks: + +1. Creating a package folder named `board/` +2. Moving `app.py` into `board/` +3. Renaming `app.py` to `__init__.py` + +You can perform these tasks by hand or use the [terminal](https://realpython.com/terminal-commands/) to perform all three steps with two commands: + +`(venv) $ mkdir board (venv) $ mv app.py board/__init__.py` + +With the commands above, you create the `board/` subfolder. Then, you move `app.py` into `board/` and rename it to `__init__.py`. + +By now, your Flask project structure should look like this: + +`rp_flask_board/ │ └── board/ └── __init__.py` + +With the new package structure in place, make sure that you stay in the `rp_flask_board/` folder and run your Flask project with this command: + +`(venv) $ python -m flask --app board run --port 8000 --debug` + +With the command above, you’re telling Flask to look for an app named `board` and serve it in debug mode on port `8000`. When you visit `http://localhost:8000`, you see the same _Hello, World!_ displayed as before. + +[Remove ads](https://realpython.com/account/join/) + +### Work With an Application Factory[](https://realpython.com/flask-project/#work-with-an-application-factory "Permanent link") + +An **application factory** in Flask is a design pattern that’s highly beneficial for scaling Flask projects. With an application factory, you can create and configure your Flask project flexibly and efficiently, making it easier to develop, test, and maintain as it grows and evolves. + +Instead of having your application’s code at the root level of your `__init__.py` file, you’ll work with a function that returns your application. To do so, replace the content of `__init__.py` with the content below: + +`board/__init__.py` + +`from flask import Flask def create_app(): app = Flask(__name__) return app` + +After importing `Flask`, you create a function named `create_app()` that initializes the app and returns it. The `create_app()` function is your application factory. + +With an application factory, your project’s structure becomes more organized. It encourages you to separate different parts of your application, like routes, configurations, and initializations, into different files later on. This encourages a cleaner and more maintainable codebase. + +To see the benefits of an application factory in action, you’ll create your first blueprint in the next section. + +## Leverage Blueprints[](https://realpython.com/flask-project/#leverage-blueprints "Permanent link") + +As your Flask project grows, you have lots of view functions and other related bits of code that work together. Instead of adding all these directly to a basic `app.py` file, you can create **blueprints** that you register in your application factory. + +[Blueprints](https://realpython.com/flask-blueprint/) are modules that contain related views that you can conveniently import in `__init__.py`. For example, you’ll have a blueprint that stores the main pages of your project. + +Create a file named `pages.py` in the `board/` folder and add the content below: + +`board/pages.py` + +`from flask import Blueprint bp = Blueprint("pages", __name__) @bp.route("/") def home(): return "Hello, Home!" @bp.route("/about") def about(): return "Hello, About!"` + +After importing `Blueprint`, you create an instance of it named `bp`. The first argument, `"pages"`, is the name of your blueprint. You’ll use this name to identify this particular blueprint in your Flask project. The second argument is the blueprint’s `__name__`. You’ll use this later when you import `pages` into `__init__.py`. + +Then, you define two routes, one as the `home` view and the other as the `about` view. Each of them returns a string to indicate on which page you are on. + +Before you can visit the pages, you need to connect the `pages` blueprint with your Flask project: + +`board/__init__.py` + +`from flask import Flask from board import pages def create_app(): app = Flask(__name__) app.register_blueprint(pages.bp) return app` + +Once you’ve imported and registered the `pages` blueprint in your application factory, you can visit the routes that you defined in `pages.py` in your browser. When you visit `http://localhost:8000/about`, then you can see the _Hello, About!_ string: + +[![Unstyled about page](https://files.realpython.com/media/02-hello-about.5a86d9ac9395.png)](https://files.realpython.com/media/02-hello-about.5a86d9ac9395.png) + +If the main purpose of your Flask project were to just display plain strings, then you’d be done. However, it’s more fun to actually display dynamic content to your users. That’s when templates come into play. + +## Introduce Templates[](https://realpython.com/flask-project/#introduce-templates "Permanent link") + +Templates are [HTML files](https://realpython.com/html-css-python/#create-your-first-html-file) with the capability of rendering dynamic content sent over from your Flask views. For this, Flask uses the popular [Jinja](https://realpython.com/primer-on-jinja-templating/) **template engine**, which you already installed as a dependency when you installed Flask. + +With a template engine like Jinja, you can embed Python-like expressions into your templates to create dynamic web content. You can use loops, conditionals, and variables directly in your templates. + +Jinja also supports **template inheritance**, allowing the creation of a **base template** that you can extend in **child templates**, promoting code reuse and a consistent layout across different pages of your project. + +[Remove ads](https://realpython.com/account/join/) + +### Build a Base Template[](https://realpython.com/flask-project/#build-a-base-template "Permanent link") + +Create a new template named `base.html` in a `templates/` directory inside `board/`: + +`board/templates/base.html` + +` Message Board - {% block title %}{% endblock title %}

    Message Board

    {% block header %}{% endblock header %}
    {% block content %}

    No messages.

    {% endblock content %}
    ` + +Commonly, the Jinja base template is named `base.html`, and it contains the main HTML structure of your web pages. The main structure of `base.html` is similar to a normal HTML page. You start by declaring the [doctype](https://developer.mozilla.org/en-US/docs/Glossary/Doctype), wrapping everything in `` tags, and setting the [`lang` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang). + +Then you go on to add `` and `` with some other nested elements. In line 4, you set the title of your project to _Message Board_. The empty `title` block gives you the opportunity to extend the title with a child template. + +**Note:** The message board is just an example for a generic Flask project. Feel free to give your Flask project a more fitting name. + +In line 10, you set the `header` block. If a child template doesn’t contain a `header` block, then `
    ` will stay empty. + +By providing default content inside the `content` block in line 13, you either display the _No messages_ hint or show the content of the child template. + +### Add Your Child Templates[](https://realpython.com/flask-project/#add-your-child-templates "Permanent link") + +Your base template is designed to provide a consistent structure for your project while allowing flexibility in specific parts of the content through Jinja’s block functionality. Next, create the child templates that extend `base.html` and fill in these blocks with their specific content. + +Start with the template for your `home` view by creating a `home.html` file in a `pages/` subfolder of your `templates/` folder: + +`board/templates/pages/home.html` + +`{% extends 'base.html' %} {% block header %}

    {% block title %}Home{% endblock title %}

    {% endblock header %} {% block content %}

    Learn more about this project by visiting the About page.

    {% endblock content %}` + +To connect the child template with its parent template, you must add an `{% extends %}` tag at the top of the file. + +Child templates also contain `{% block %}` tags. By providing the block’s name as an argument, you’re connecting the blocks from the child template with the blocks from the parent template. + +When you use [`url_for()`](https://flask.palletsprojects.com/en/3.0.x/api/#flask.Flask.url_for), Flask creates the full URL to the given view for you. This means that if you change the route in your Python code, then the URL in your templates updates automatically. + +Continue by creating a file named `about.html` in the same `pages/` directory: + +`board/templates/pages/about.html` + +`{% extends 'base.html' %} {% block header %}

    {% block title %}About{% endblock title %}

    {% endblock header %} {% block content %}

    This is a message board for friendly messages.

    {% endblock content %}` + +Just like in `home.html`, you do something nifty with the `title` block. You add the page’s title inside the `header` block and wrap it within `title`. Jinja will understand this structure and render the page’s title in the `header` and `title` blocks. + +With both child templates in place, you need to adjust your views to return the templates instead of the plain strings. Hop over to `pages.py` and adjust `home()` and `about()`: + +`board/pages.py` + +`from flask import Blueprint, render_template bp = Blueprint("pages", __name__) @bp.route("/") def home(): return render_template("pages/home.html") @bp.route("/about") def about(): return render_template("pages/about.html")` + +After importing Flask’s [`render_template()`](https://flask.palletsprojects.com/en/3.0.x/api/#flask.render_template), you can use the function to return the `home.html` and `about.html` templates that you placed in the `templates/pages/` folder. + +By default, Flask expects your templates to be in a `templates/` directory. Therefore, you don’t need to include `templates/` in the path of the templates. + +To verify that your templates work, restart your Flask development server and visit `http://localhost:8000`: + +[![Unstyled Home page](https://files.realpython.com/media/03-home.05daf2dda36d.png)](https://files.realpython.com/media/03-home.05daf2dda36d.png) + +Your _Home_ page shows the dynamic title. + +When you visit your _Home_ page, then you can click the link to the _About_ page. Since there’s no link to the _Home_ page, you’d need to either use the _Back_ button of your browser or enter the URL manually in the address bar. + +It seems like it’s time to elevate the user experience and include a navigation menu in your project! + +[Remove ads](https://realpython.com/account/join/) + +## Improve the User Experience[](https://realpython.com/flask-project/#improve-the-user-experience "Permanent link") + +A good user experience is crucial in any web application. It ensures that users find the application not only convenient to use, but also enjoyable. + +In the upcoming sections, you’ll add a navigation menu and style your web application. While doing so, notice how these additions can contribute to a better user experience. + +### Include a Navigation Menu[](https://realpython.com/flask-project/#include-a-navigation-menu "Permanent link") + +The navigation of a website is usually displayed on every page. With your base and child template structure, it’s best to add the code for the navigation menu into `base.html`. + +Instead of adding the navigation menu code directly into `base.html`, you can leverage the `{% include %}` tag. By referencing another template with `{% include %}`, you’re loading the whole template into that position. If you need to make any changes in the navigation, then you know exactly where to look. Additionally, you can decide to include your navigation template on a different part of the page, for example when you [design a `404` error template](https://realpython.com/flask-logging-messages/#design-the-404-error-template). + +**Included templates** are partials that contain a fraction of the full HTML code. To indicate that a template is meant to be included, you can prefix its name with an underscore (`_`). + +Follow the prefix-based naming scheme and create a new template named `_navigation.html` in your `templates/` folder: + +`templates/_navigation.html` + +`` + +Note that `_navigation.html` contains neither an `{% extends %}` tag nor any `{% block %}` tags. You can focus solely on how you want to render your navigation menu. + +Just like above, you use `url_for()`, and Flask creates the full URL to the given view for you. So, even when you decide to change the route to one of your pages, the navigation menu will still work. + +Include `_navigation.html` in `base.html` to display your navigation menu on all of your pages: + +`templates/base.html` + +` Message Board - {% block title %}{% endblock title %}

    Message Board

    {% include("_navigation.html") %}
    {% block header %}{% endblock header %}
    {% block content %}

    No messages.

    {% endblock content %}
    ` + +Instead of adding the navigation menu code directly into `base.html`, you include `_navigation.html` in your website’s header. + +Visit `http://localhost:8000/about` to check out your new navigation menu: + +[![Unstyled About page with a menu](https://files.realpython.com/media/04-about-with-menu.3aa627239a41.png)](https://files.realpython.com/media/04-about-with-menu.3aa627239a41.png) + +Since both `home.html` and `about.html` extend `base.html`, you didn’t need to make any changes in these templates to make the navigation menu appear. That’s template inheritance in action! + +But wait, there’s more! In the next section, you’ll leverage template inheritance to add consistent styling to your web project. + +### Make Your Project Look Nice[](https://realpython.com/flask-project/#make-your-project-look-nice "Permanent link") + +The templates in your project provide the logic and structure for the **front end** of your project. With the help of **Cascading Style Sheets (CSS)**, you can [style the content](https://realpython.com/html-css-python/#style-your-content-with-css). + +In Flask projects, you commonly save CSS files in a `static/` directory. In this project, you’ll only work with one CSS file named `styles.css`. But if you decide to expand the project at some point, you can also use this folder to store images or [JavaScript files](https://realpython.com/python-vs-javascript/). + +Create a new directory named `static/` inside of `board/` and place a file named `styles.css` in it with the **CSS declarations** below: + +`board/static/styles.css` + +`* { box-sizing: border-box; } body { font-family: sans-serif; font-size: 20px; margin: 0 auto; text-align: center; } a, a:visited { color: #007bff; } a:hover { color: #0056b3; } nav ul { list-style-type: none; padding: 0; } nav ul li { display: inline; margin: 0 5px; } main { width: 80%; margin: 0 auto; }` + +The CSS declarations above ensure that the web elements are properly spaced and sized, making the website look organized and more convenient to navigate. + +The color scheme for the links provides a visual cue to users about clickable elements. The font choice and size contribute to readability. The overall layout and alignment of the web elements give the website a clean and modern look. + +With the style sheet in place, you need to add a link to `styles.css` inside `` of `base.html`: + +`templates/base.html` + +` Message Board - {% block title %}{% endblock title %} ` + +You can reference a CSS file with a `` tag in the header of your HTML page. Just like before, you use `url_for()` to create the full URL for the `href` attribute. To link to the `styles.css` file stored in your Flask project’s `static/` folder specifically, you use the `filename` argument. + +By adding the CSS file reference to `base.html`, you’re again taking advantage of the inheritance mechanism that Jinja templates provide. You only need to add `styles.css` in your base template to make it present in your child templates. + +You may need to restart your Flask development server again to see your styling in action: + +[![About page with styling](https://files.realpython.com/media/05-about-styled.5f9a679b6b21.png)](https://files.realpython.com/media/05-about-styled.5f9a679b6b21.png) + +With some minimal styling, your Flask web project is starting to look like a finished web app. Feel free to add more pages and content on your own. Once you’re finished, you can continue to work on the message board project by [adding a database](https://realpython.com/flask-database/) and accepting posts from your users. + +[Remove ads](https://realpython.com/account/join/) + +## Conclusion[](https://realpython.com/flask-project/#conclusion "Permanent link") + +Congratulations on successfully setting up a Flask project. This working Flask web project is a great starting point for any future Flask projects that you may have. By understanding these foundational concepts, you’re now well equipped to tackle more complex projects and further explore the capabilities of Flask. + +**In this tutorial, you’ve learned how to:** + +- Set up a **Flask project** +- Create a `"Hello, World!"` **Flask app** +- Add **multiple pages** +- Leverage **Jinja templates** +- Store **static files** + +You’ve successfully created a working Flask web application that you can use to bootstrap your future Flask projects. \ No newline at end of file diff --git a/Computerkram/Webseiten, selbstgehostet/Flask Dummy Webseite über WWW (Chatbot Session).md b/Computerkram/Webseiten, selbstgehostet/Flask Dummy Webseite über WWW (Chatbot Session).md new file mode 100644 index 0000000..7ed9c5b --- /dev/null +++ b/Computerkram/Webseiten, selbstgehostet/Flask Dummy Webseite über WWW (Chatbot Session).md @@ -0,0 +1,374 @@ +User: In diesem Skript starte ich eine Dummy Webseite. WIe kann ich diese mit den vorhandenen Werkzeugen (traefik) übers WWW verfügbar machen? + +Workspace: Collecting workspace informationUm deine Flask-Dummy-Website über Traefik im WWW verfügbar zu machen, musst du sie containerisieren und mit Traefik-Labels konfigurieren. Hier ist die Lösung: + +## 1. Dockerfile erstellen + +````dockerfile +FROM python:3.11-slim + +WORKDIR /app + +# Flask installieren +RUN pip install --no-cache-dir flask + +# App-Code kopieren +COPY my_app/ /app/my_app/ + +# Port exponieren +EXPOSE 8000 + +# App starten +CMD ["python", "-m", "flask", "--app", "my_app", "run", "--host", "0.0.0.0", "--port", "8000"] +```` + +## 2. Docker Compose Konfiguration erstellen + +````yaml +services: + dummy_website: + build: . + container_name: dummy_website + restart: unless-stopped + + expose: + - "8000" + + networks: + - proxy + + labels: + # Traefik aktivieren + - "traefik.enable=true" + + # Router-Konfiguration + - "traefik.http.routers.dummy.rule=Host(`demo.schneiderserver.site`)" + - "traefik.http.routers.dummy.entrypoints=websecure" + - "traefik.http.routers.dummy.tls.certresolver=myresolver" + + # Service-Konfiguration + - "traefik.http.services.dummy.loadbalancer.server.port=8000" + - "traefik.http.services.dummy.loadbalancer.server.scheme=http" + + # Optionale Sicherheits-Headers + - "traefik.http.middlewares.dummy-headers.headers.customresponseheaders.X-Frame-Options=SAMEORIGIN" + - "traefik.http.middlewares.dummy-headers.headers.customresponseheaders.X-Content-Type-Options=nosniff" + - "traefik.http.routers.dummy.middlewares=dummy-headers" + +networks: + proxy: + external: true + name: traefik_proxy +```` + +## 3. Flask-App für Docker anpassen + +````python +from flask import Flask + +from my_app import pages + +def create_app(): + app = Flask(__name__) + + # Wichtig für Reverse-Proxy-Betrieb + app.config['PREFERRED_URL_SCHEME'] = 'https' + + app.register_blueprint(pages.pages_bp) + return app +```` + +## 4. Starten der Website + +```bash +cd /opt/dummy_website +docker compose up -d +``` + +## 5. manage.sh erweitern (optional) + +````sh +// ...existing code... + +manage_single_service() { + SERVICE=$1 + ACTION=$2 + + case $SERVICE in + traefik) + cd /opt/traefik + ;; + nextcloud) + cd /opt/nextcloud + ;; + navidrome) + cd /opt/navidrome + ;; + dummy) + cd /opt/dummy_website + ;; + *) + echo -e "${RED}❌ Unbekannter Service: $SERVICE${NC}" + exit 1 + ;; + esac + + case $ACTION in + start|stop|restart|logs) + docker compose $ACTION + ;; + *) + docker compose $ACTION + ;; + esac +} + +// ...existing code... + + traefik|nextcloud|navidrome|dummy) + if [ -n "$2" ]; then + manage_single_service $1 $2 + else + echo "Verwendung: $0 $1 [start|stop|restart|logs]" + fi + ;; + +// ...existing code... +```` + +## 6. DNS-Eintrag erstellen + +Erstelle einen A-Record für `demo.schneiderserver.site` mit der IP-Adresse deines Servers. + +## Zugriff + +Nach erfolgreicher Konfiguration ist deine Website erreichbar unter: +- **URL:** `https://demo.schneiderserver.site` +- **SSL:** Automatisch via Let's Encrypt +- **HTTP → HTTPS:** Automatische Weiterleitung + +## Verwaltung + +```bash +# Status prüfen +docker ps | grep dummy_website + +# Logs anzeigen +/opt/manage.sh dummy logs + +# Neustart +/opt/manage.sh dummy restart + +# Stoppen +/opt/manage.sh dummy stop +``` + +**Wichtig:** Ändere `demo.schneiderserver.site` in den Labels zu deiner gewünschten Domain und erstelle den entsprechenden DNS-Eintrag. + +User: Geht es auch einfacher. ICh will (noch) nicht containerisieren. Erstmal nur test, ob und wie ich die Web App, die lokal auf Port 8000 läuft übers WWW erreichen kann, im Zweifel auch erstmal ohne traefik + +GitHub Copilot: Ja, das geht viel einfacher! Hier sind die Optionen: + +## Option 1: Direkt mit Traefik (ohne Container) + +Traefik kann auch auf lokale Services weiterleiten. Erstelle eine **dynamische Konfiguration**: + +````yaml +http: + routers: + dummy-local: + rule: "Host(`demo.schneiderserver.site`)" + entryPoints: + - websecure + service: dummy-local-service + tls: + certResolver: myresolver + middlewares: + - dummy-headers + + services: + dummy-local-service: + loadBalancer: + servers: + - url: "http://127.0.0.1:8000" + + middlewares: + dummy-headers: + headers: + customResponseHeaders: + X-Frame-Options: "SAMEORIGIN" +```` + +Dann Traefik konfigurieren, um die Datei zu laden: + +````yaml +services: + traefik: + image: traefik:v3.6 + container_name: traefik + restart: unless-stopped + + command: + # ...existing code... + - --providers.docker.network=traefik_proxy + - --providers.docker.useBindPortIP=false + - --providers.docker.defaultRule=Host(`{{ normalize .Name }}.schneiderserver.site`) + + # 📁 File Provider aktivieren + - --providers.file.directory=/etc/traefik/dynamic + - --providers.file.watch=true + + # ...existing code... + + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./letsencrypt:/letsencrypt + - ./dynamic:/etc/traefik/dynamic:ro +```` + +```bash +# Ordner erstellen und Traefik neustarten +mkdir -p /opt/traefik/dynamic +# Datei erstellen (siehe oben) +docker compose -f /opt/traefik/docker-compose.yml restart +``` + +## Option 2: Ohne Traefik - SSH Tunnel (schnellster Test) + +Auf deinem **lokalen Rechner**: + +```bash +ssh -L 8000:localhost:8000 user@schneiderserver.site +# Dann im Browser: http://localhost:8000 +``` + +## Option 3: Ohne Traefik - Flask direkt exponieren (UNSICHER!) + +**Nur zum Testen, NICHT für Produktion:** + +````sh +python -m flask --app my_app run --host 0.0.0.0 --port 8000 --debug +```` + +```bash +# Firewall-Regel temporär öffnen +sudo ufw allow 8000/tcp + +# Zugriff dann über: http://schneiderserver.site:8000 +``` + +**⚠️ Achtung:** Das ist unverschlüsselt (kein HTTPS) und unsicher! + +## Empfehlung + +**Option 1 (Traefik mit File Provider)** ist ideal für deinen Use-Case: +- ✅ Kein Docker für deine App nötig +- ✅ Automatisches HTTPS +- ✅ Professionell +- ✅ Schnell umgesetzt + +Nach der Konfiguration: +1. DNS-Eintrag für `demo.schneiderserver.site` erstellen +2. Flask-App starten: `bash /opt/dummy_website/app.sh` +3. Zugriff: `https://demo.schneiderserver.site` + +Welche Option möchtest du testen? + +User: # Firewall-Regel temporär öffnen +sudo ufw allow 8000/tcp + +# Zugriff dann über: http://schneiderserver.site:8000 + +wie schließe ich den Port nach Test wieder? + +GitHub Copilot: Um den Port nach dem Test wieder zu schließen: + +```bash +# Port 8000 wieder schließen +sudo ufw delete allow 8000/tcp + +# Status überprüfen +sudo ufw status +``` + +--- + +**Aber ich würde dir wirklich Option 1 empfehlen** (Traefik mit File Provider). Das ist genauso schnell und du musst keine Firewall-Regeln ändern: + +## Schritt-für-Schritt: + +### 1. Docker Compose erweitern + +````yaml + command: + # ...existing code... + - --providers.docker.defaultRule=Host(`{{ normalize .Name }}.schneiderserver.site`) + + # 📁 File Provider aktivieren + - --providers.file.directory=/etc/traefik/dynamic + - --providers.file.watch=true + + # ------------------------ + # 🌍 EntryPoints + # ------------------------ + # ...existing code... + + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./letsencrypt:/letsencrypt + - ./dynamic:/etc/traefik/dynamic:ro +```` + +### 2. Dynamic Config erstellen + +```bash +mkdir -p /opt/traefik/dynamic +nano /opt/traefik/dynamic/dummy-website.yml +``` + +````yaml +http: + routers: + dummy-local: + rule: "Host(`demo.schneiderserver.site`)" + entryPoints: + - websecure + service: dummy-local-service + tls: + certResolver: myresolver + + services: + dummy-local-service: + loadBalancer: + servers: + - url: "http://127.0.0.1:8000" +```` + +### 3. Traefik neustarten + +```bash +cd /opt/traefik +docker compose restart +``` + +### 4. Flask-App starten + +```bash +cd /opt/dummy_website +bash app.sh +``` + +### 5. Testen + +```bash +# DNS-Eintrag für demo.schneiderserver.site erstellen +# Dann im Browser: https://demo.schneiderserver.site +``` + +**Vorteile:** +- ✅ Kein Firewall-Port öffnen nötig +- ✅ Automatisches HTTPS +- ✅ Saubere Lösung +- ✅ Einfach wieder zu entfernen (Datei löschen) + +Möchtest du es so probieren? \ No newline at end of file diff --git a/Computerkram/Webseiten, selbstgehostet/Webdesign Start - aller Anfang ist schwer.md b/Computerkram/Webseiten, selbstgehostet/Webdesign Start - aller Anfang ist schwer.md new file mode 100644 index 0000000..ce7dc29 --- /dev/null +++ b/Computerkram/Webseiten, selbstgehostet/Webdesign Start - aller Anfang ist schwer.md @@ -0,0 +1,10 @@ +1. Initialer Entwurf von ChatGPT (oder anderen LLM), evtl. mit Verweis auf Vorbild-Seite +2. Öffnen der HTML Seite in Editor + - Blue Griffon + - [http://bluegriffon-epubedition.com/BGEE.html](http://bluegriffon-epubedition.com/BGEE.html) + - Installer für Windows und Debian Derivate + - 😦 nicht für Arch-Derivate (Cachy) + - SeaMonkey + - 😀 Im AUR enthalten: `paru -S seamonkey` + - Geht auch in VS Code oder VS Codeum + - Kein WYSIWYG aber Live Preview \ No newline at end of file diff --git a/Computerkram/etc/fstab - Bsp buntes_monster.md b/Computerkram/etc/fstab - Bsp buntes_monster.md new file mode 100644 index 0000000..7e88032 --- /dev/null +++ b/Computerkram/etc/fstab - Bsp buntes_monster.md @@ -0,0 +1,17 @@ +```bash +# /etc/fstab: static file system information. +# +# Use 'blkid' to print the universally unique identifier for a +# device; this may be used with UUID= as a more robust way to name devices +# that works even if disks are added and removed. See fstab(5). +# +# +# / was on /dev/nvme0n1p2 during installation +UUID=4d4554dc-e3fc-499c-991c-074655585d11 / ext4 errors=remount-ro 0 1 +# /boot/efi was on /dev/nvme0n1p1 during installation +UUID=FCBD-00BE /boot/efi vfat umask=0077 0 1 +/swapfile none swap sw 0 0 +UUID=04F6962EF6961FCA /media/mathias/Anbau2 ntfs-3g defaults,umask=000,uid=1000,gid=1000 0 0 +UUID=A8F0EC77F0EC4D5E /media/mathias/Bilder ntfs-3g defaults,umask=000,uid=1000,gid=1000 0 0 +UUID=a642b8a8-2cdd-4635-a094-e408073a236d /media/mathieu/vault ext4 defaults 0 2 +``` \ No newline at end of file diff --git a/Computerkram/git/Git_Fork_Guide.md b/Computerkram/git/Git_Fork_Guide.md new file mode 100644 index 0000000..4f4b23c --- /dev/null +++ b/Computerkram/git/Git_Fork_Guide.md @@ -0,0 +1,74 @@ +# Anleitung: Template lokal forken (ohne Git-History) + +Diese Anleitung beschreibt die Schritte aus diesem Chat, um ein Projekt-Template lokal zu klonen und mit einer frischen Git-History neu zu starten. + +## Voraussetzungen + +- Git ist installiert. +- Zugriff auf das Template-Repository ist moeglich (SSH oder HTTPS). +- Zielordner fuer das neue Projekt ist bekannt. + +## Schritte + +1. In den Zielordner wechseln: + + ```bash + cd /home/mathias/dev/web/foton + ``` + +2. Template klonen (SSH bevorzugt): + + ```bash + git clone git@github.com:mathias2784/my_flask_temp.git foton_website + ``` + +3. Falls SSH fehlschlaegt, mit HTTPS klonen: + + ```bash + git clone https://github.com/mathias2784/my_flask_temp.git foton_website + ``` + +4. In das neue Projekt wechseln: + + ```bash + cd foton_website + ``` + +5. Alte Git-History entfernen und frisches Repo initialisieren: + + ```bash + rm -rf .git + git init + ``` + +## Optionale Naechste Schritte + +- Standard-Branch auf main umbenennen: + + ```bash + git branch -m main + ``` + +- Neues Remote-Repository hinzufuegen: + + ```bash + git remote add origin + ``` + +- Initialen Commit erstellen: + + ```bash + git add -A + git commit -m "Initial commit" + ``` + +- Push zum neuen Remote: + + ```bash + git push -u origin main + ``` + +## Hinweise + +- Beim ersten SSH-Connect kann eine Host-Key-Abfrage erscheinen. Diese einmalig bestaetigen. +- Wenn SSH immer noch fehlschlaegt, HTTPS verwenden oder SSH-Key in GitHub einrichten. diff --git a/Computerkram/git/Ignore & Untrack.md b/Computerkram/git/Ignore & Untrack.md new file mode 100644 index 0000000..bd4206f --- /dev/null +++ b/Computerkram/git/Ignore & Untrack.md @@ -0,0 +1,63 @@ +Das Verhalten ist korrekt 🙂 +`.gitignore` wirkt **nur für Dateien, die noch nicht von Git getrackt werden**. + +Deine Datei `hypr/.config/hypr/env` wurde offenbar schon einmal committed. Deshalb ignoriert Git sie nicht automatisch, auch wenn sie jetzt in `.gitignore` steht. + +--- + +## ✅ Lösung: Datei aus dem Index entfernen (aber lokal behalten) + +Führe folgenden Befehl aus: + +```bash +git rm --cached hypr/.config/hypr/env +``` + +Danach committen: + +```bash +git commit -m "Stop tracking hypr env file" +``` + +Jetzt: + +- Die Datei bleibt lokal erhalten ✅ + +- Git trackt sie nicht mehr ✅ + +- Änderungen erscheinen nicht mehr in `git status` ✅ + + +--- + +## 🔎 Warum das so ist + +`.gitignore` verhindert nur das **Neu-Tracken** von Dateien. +Bereits versionierte Dateien bleiben im Index, bis man sie explizit entfernt (`git rm --cached`). + +--- + +## 💡 Falls du viele Dateien entfernen willst + +Für alle Dateien, die jetzt durch `.gitignore` ignoriert werden sollen: + +```bash +git rm -r --cached . +git add . +git commit -m "Reapply gitignore" +``` + +⚠️ Das betrifft das ganze Repository – nur verwenden, wenn du weißt, was du tust. + +--- + +Wenn du möchtest, erkläre ich dir auch kurz den Unterschied zwischen: + +- Working Directory + +- Index (Staging Area) + +- Repository + + +Das hilft extrem beim Verständnis von Git. \ No newline at end of file diff --git a/Computerkram/neovim-setup.md b/Computerkram/neovim-setup.md new file mode 100644 index 0000000..c7b55fe --- /dev/null +++ b/Computerkram/neovim-setup.md @@ -0,0 +1,1247 @@ +# Neovim IDE Setup Guide + +A comprehensive guide to setting up Neovim as a full-featured IDE for Python, Shell scripts, and more using Lua configuration. + +## Table of Contents + +1. [Prerequisites](#prerequisites) +2. [Directory Structure](#directory-structure) +3. [Configuration Files](#configuration-files) + - [init.lua](#initlua) + - [lua/plugins/init.lua](#luapluginsinitlua) + - [lua/plugins/lsp.lua](#luapluginslsplua) + - [lua/plugins/dap.lua](#luapluginsdaplua) + - [lua/plugins/treesitter.lua](#luapluginstreesitterlua) + - [lua/plugins/telescope.lua](#luapluginstelescopelua) + - [lua/plugins/nvimtree.lua](#luapluginsnvimtreelua) + - [lua/plugins/cmp.lua](#luapluginscmplua) + - [lua/plugins/toggleterm.lua](#luapluginstoggletermlua) + - [lua/plugins/formatter.lua](#luapluginsformatterlua) +4. [Installing Language Servers](#installing-language-servers) +5. [Keybindings Reference](#keybindings-reference) +6. [First Launch](#first-launch) + +--- + +## Prerequisites + +### Install Neovim (v0.9+) + +**Ubuntu/Debian:** +```bash +sudo add-apt-repository ppa:neovim-ppa/unstable +sudo apt update +sudo apt install neovim +``` + +**Fedora:** +```bash +sudo dnf install neovim +``` + +**Arch Linux:** +```bash +sudo pacman -S neovim +``` + +**macOS:** +```bash +brew install neovim +``` + +### Install Required Tools + +```bash +# Node.js (for LSP servers via Mason) +curl -fsSL https://fnm.vercel.app/install | bash +source ~/.bashrc +fnm install --latest + +# Python (for Python LSP and debugging) +pip install python-lsp-server debugpy + +# ripgrep (for telescope live grep) +sudo apt install ripgrep # Ubuntu +sudo dnf install ripgrep # Fedora +sudo pacman -S ripgrep # Arch +brew install ripgrep # macOS + +# git (for plugin installation) +sudo apt install git +``` + +--- + +## Directory Structure + +Create the following directory structure: + +```bash +mkdir -p ~/.config/nvim/lua/plugins +``` + +Your final structure should look like: + +``` +~/.config/nvim/ +├── init.lua +└── lua/ + └── plugins/ + ├── init.lua + ├── lsp.lua + ├── dap.lua + ├── treesitter.lua + ├── telescope.lua + ├── nvimtree.lua + ├── cmp.lua + ├── toggleterm.lua + └── formatter.lua +``` + +--- + +## Configuration Files + +### ~/.config/nvim/init.lua + +Main entry point for Neovim configuration. + +```lua +-- Leader key +vim.g.mapleader = " " +vim.g.maplocalleader = " " + +-- General settings +vim.opt.number = true +vim.opt.relativenumber = true +vim.opt.tabstop = 4 +vim.opt.shiftwidth = 4 +vim.opt.expandtab = true +vim.opt.smartindent = true +vim.opt.wrap = false +vim.opt.scrolloff = 8 +vim.opt.signcolumn = "yes" +vim.opt.termguicolors = true +vim.opt.cursorline = true + +-- Enable clipboard +vim.opt.clipboard = "unnamedplus" + +-- Search settings +vim.opt.ignorecase = true +vim.opt.smartcase = true +vim.opt.hlsearch = true + +-- Split settings +vim.opt.splitright = true +vim.opt.splitbelow = true + +-- Performance +vim.opt.updatetime = 50 +vim.opt.timeoutlen = 300 + +-- Set colorscheme +vim.cmd.colorscheme "tokyonight" + +-- Load plugins +require("plugins") + +-- Keybindings +local keymap = vim.keymap.set + +-- Better window navigation +keymap("n", "", "h", { desc = "Navigate left" }) +keymap("n", "", "j", { desc = "Navigate down" }) +keymap("n", "", "k", { desc = "Navigate up" }) +keymap("n", "", "l", { desc = "Navigate right" }) + +-- Resize windows +keymap("n", "", ":resize -2", { desc = "Resize window up" }) +keymap("n", "", ":resize +2", { desc = "Resize window down" }) +keymap("n", "", ":vertical resize -2", { desc = "Resize window left" }) +keymap("n", "", ":vertical resize +2", { desc = "Resize window right" }) + +-- Move text up/down +keymap("n", "", ":m .+1==", { desc = "Move line down" }) +keymap("n", "", ":m .-2==", { desc = "Move line up" }) +keymap("v", "", ":m '>+1gv=gv", { desc = "Move selection down" }) +keymap("v", "", ":m '<-2gv=gv", { desc = "Move selection up" }) + +-- Stay in indent mode +keymap("v", "<", "", ">gv", { desc = "Indent right" }) + +-- Better paste +keymap("v", "p", '"_dP', { desc = "Paste without yanking" }) + +-- Clear highlights +keymap("n", "h", ":nohlsearch", { desc = "Clear search highlights" }) + +-- Save and quit +keymap("n", "w", ":w", { desc = "Save file" }) +keymap("n", "q", ":q", { desc = "Quit" }) +keymap("n", "Q", ":qa!", { desc = "Force quit all" }) + +-- Toggle options +keymap("n", "tn", ":set nu!", { desc = "Toggle line numbers" }) +keymap("n", "tr", ":set rnu!", { desc = "Toggle relative numbers" }) +``` + +--- + +### ~/.config/nvim/lua/plugins/init.lua + +Plugin manager setup using lazy.nvim. + +```lua +-- Bootstrap lazy.nvim +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not vim.loop.fs_stat(lazypath) then + vim.fn.system({ + "git", + "clone", + "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", + lazypath, + }) +end +vim.opt.rtp:prepend(lazypath) + +-- Plugin specifications +require("lazy").setup({ + -- Theme + { "folke/tokyonight.nvim", lazy = false }, + + -- Plugin manager + { "folke/lazy.nvim", version = "*" }, + + -- LSP + { "neovim/nvim-lspconfig" }, + { "williamboman/mason.nvim" }, + { "williamboman/mason-lspconfig.nvim" }, + + -- Autocomplete + { "hrsh7th/nvim-cmp" }, + { "hrsh7th/cmp-nvim-lsp" }, + { "hrsh7th/cmp-buffer" }, + { "hrsh7th/cmp-path" }, + { "hrsh7th/cmp-cmdline" }, + { "L3MON4D3/LuaSnip" }, + { "saadparwaiz1/cmp_luasnip" }, + + -- Treesitter (syntax) + { "nvim-treesitter/nvim-treesitter", build = ":TSUpdate" }, + { "nvim-treesitter/nvim-treesitter-textobjects" }, + + -- Fuzzy finder + { "nvim-telescope/telescope.nvim", dependencies = { "nvim-lua/plenary.nvim" } }, + + -- File tree + { "nvim-tree/nvim-tree.lua" }, + { "nvim-tree/nvim-web-devicons" }, + + -- Terminal + { "akinsho/toggleterm.nvim" }, + + -- Debugging + { "mfussenegger/nvim-dap" }, + { "rcarriga/nvim-dap-ui" }, + { "theHamsta/nvim-dap-virtual-text" }, + + -- Formatters/Linters + { "nvimtools/none-ls.nvim" }, + { "nvim-lua/plenary.nvim" }, + + -- Utility + { "windwp/nvim-autopairs" }, + { "numToStr/Comment.nvim" }, +}) +``` + +--- + +### ~/.config/nvim/lua/plugins/lsp.lua + +LSP configuration for Python and Shell scripts. + +```lua +-- Setup Mason (LSP installer) +require("mason").setup({ + ui = { + border = "rounded", + icons = { + package_installed = "✓", + package_pending = "➜", + package_uninstalled = "✗", + }, + }, + log_level = vim.log.levels.INFO, + max_concurrent_installers = 4, +}) + +-- LSP config +local lspconfig = require("lspconfig") +local cmp_nvim_lsp = require("cmp_nvim_lsp") + +-- Capabilities for autocomplete +local capabilities = cmp_nvim_lsp.default_capabilities() + +-- Diagnostic settings +vim.diagnostic.config({ + virtual_text = true, + signs = true, + underline = true, + update_in_insert = false, + severity_sort = true, + float = { + border = "rounded", + source = true, + }, +}) + +-- Signs for diagnostics +local signs = { Error = " ", Warn = " ", Hint = "󰠠 ", Info = " " } +for type, icon in pairs(signs) do + local hl = "DiagnosticSign" .. type + vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = "" }) +end + +-- LSP handlers +vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { + border = "rounded", +}) + +vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, { + border = "rounded", +}) + +-- LSP Keybindings +local function lsp_keymaps(bufnr) + local opts = { buffer = bufnr, silent = true } + + vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts) + vim.keymap.set("n", "gD", vim.lsp.buf.declaration, opts) + vim.keymap.set("n", "gi", vim.lsp.buf.implementation, opts) + vim.keymap.set("n", "gr", vim.lsp.buf.references, opts) + vim.keymap.set("n", "K", vim.lsp.buf.hover, opts) + vim.keymap.set("n", "rn", vim.lsp.buf.rename, opts) + vim.keymap.set("n", "ca", vim.lsp.buf.code_action, opts) + vim.keymap.set("n", "e", vim.diagnostic.open_float, opts) + vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, opts) + vim.keymap.set("n", "]d", vim.diagnostic.goto_next, opts) +end + +-- Python LSP +lspconfig.pyright.setup({ + capabilities = capabilities, + on_attach = function(client, bufnr) + lsp_keymaps(bufnr) + -- Disable virtual text for python if needed + -- client.server_capabilities.semanticTokensProvider = nil + end, + settings = { + python = { + analysis = { + typeCheckingMode = "basic", + autoSearchPaths = true, + useLibraryCodeForTypes = true, + }, + }, + }, +}) + +-- Bash LSP +lspconfig.bashls.setup({ + capabilities = capabilities, + on_attach = function(client, bufnr) + lsp_keymaps(bufnr) + end, +}) + +-- HTML, CSS, JSON (optional) +lspconfig.html.setup({ + capabilities = capabilities, + on_attach = lsp_keymaps, +}) + +lspconfig.jsonls.setup({ + capabilities = capabilities, + on_attach = lsp_keymaps, +}) + +-- Lua LSP (for neovim config editing) +lspconfig.lua_ls.setup({ + capabilities = capabilities, + on_attach = function(client, bufnr) + lsp_keymaps(bufnr) + end, + settings = { + Lua = { + runtime = { + version = "LuaJIT", + }, + diagnostics = { + globals = { "vim" }, + }, + workspace = { + library = vim.api.nvim_get_runtime_file("", true), + checkThirdParty = false, + }, + telemetry = { + enable = false, + }, + }, + }, +}) + +-- Setup Mason LSP config +require("mason-lspconfig").setup({ + ensure_installed = { + "pyright", + "bashls", + "html", + "jsonls", + "lua_ls", + }, + handlers = { + function(server_name) + require("lspconfig")[server_name].setup({ + capabilities = capabilities, + }) + end, + }, +}) +``` + +--- + +### ~/.config/nvim/lua/plugins/dap.lua + +Debug Adapter Protocol configuration for debugging Python. + +```lua +local dap = require("dap") +local dapui = require("dapui") + +-- Setup DAP UI +dapui.setup({ + icons = { expanded = "▾", collapsed = "▸", current_frame = "▸" }, + mappings = { + expand = { "", "<2-LeftMouse>" }, + open = "o", + remove = "d", + edit = "e", + repl = "r", + toggle = "t", + }, + expand_lines = vim.fn.has("nvim-0.7") == 1, + layouts = { + { + elements = { + { id = "scopes", size = 0.25 }, + { id = "breakpoints", size = 0.25 }, + { id = "stacks", size = 0.25 }, + { id = "watches", size = 0.25 }, + }, + size = 0.25, + position = "right", + }, + { + elements = { + { id = "repl", size = 0.5 }, + { id = "console", size = 0.5 }, + }, + position = "bottom", + size = 0.25, + }, + }, + floating = { + max_height = nil, + max_width = nil, + border = "rounded", + mappings = { + close = { "q", "" }, + }, + }, + windows = { indent = 1 }, +}) + +-- Open DAP UI automatically +dap.listeners.after.event_initialized["dapui_config"] = function() + dapui.open() +end +dap.listeners.before.event_terminated["dapui_config"] = function() + dapui.close() +end +dap.listeners.before.event_exited["dapui_config"] = function() + dapui.close() +end + +-- Python debug adapter configuration + dap.configurations.python = { + { + type = "python", + request = "launch", + name = "Launch file", + program = "${file}", + pythonPath = function() + return vim.fn.exepath("python3") or "python" + end, + }, + { + type = "python", + request = "launch", + name = "Debug current file (integrated terminal)", + program = "${file}", + console = "integratedTerminal", + pythonPath = function() + return vim.fn.exepath("python3") or "python" + end, + }, + { + type = "python", + request = "launch", + name = "Debug with arguments", + program = "${file}", + args = function() + local args = vim.fn.input("Args: ", ""):split(" ") + return args + end, + console = "integratedTerminal", + pythonPath = function() + return vim.fn.exepath("python3") or "python" + end, + }, +} + +-- DAP keybindings +vim.keymap.set("n", "db", dap.toggle_breakpoint, { desc = "Toggle breakpoint" }) +vim.keymap.set("n", "dc", dap.continue, { desc = "Continue" }) +vim.keymap.set("n", "ds", dap.step_over, { desc = "Step over" }) +vim.keymap.set("n", "di", dap.step_into, { desc = "Step into" }) +vim.keymap.set("n", "do", dap.step_out, { desc = "Step out" }) +vim.keymap.set("n", "dr", dap.repl.open, { desc = "Open REPL" }) +vim.keymap.set("n", "dl", dap.run_last, { desc = "Run last debug config" }) +vim.keymap.set("n", "du", dapui.toggle, { desc = "Toggle DAP UI" }) +``` + +--- + +### ~/.config/nvim/lua/plugins/treesitter.lua + +Treesitter configuration for syntax highlighting. + +```lua +require("nvim-treesitter.configs").setup({ + ensure_installed = { + "python", + "bash", + "lua", + "html", + "css", + "javascript", + "typescript", + "json", + "yaml", + "markdown", + "markdown_inline", + "go", + "rust", + "c", + "cpp", + }, + sync_install = false, + auto_install = true, + highlight = { + enable = true, + additional_vim_regex_highlighting = false, + }, + indent = { + enable = true, + }, + textobjects = { + select = { + enable = true, + lookahead = true, + keymaps = { + ["af"] = "@function.outer", + ["if"] = "@function.inner", + ["ac"] = "@class.outer", + ["ic"] = "@class.inner", + ["aa"] = "@parameter.outer", + ["ia"] = "@parameter.inner", + }, + }, + move = { + enable = true, + set_jumps = true, + goto_next_start = { + ["]f"] = "@function.outer", + ["]c"] = "@class.outer", + }, + goto_next_end = { + ["]F"] = "@function.outer", + ["]C"] = "@class.outer", + }, + goto_previous_start = { + ["[f"] = "@function.outer", + ["[c"] = "@class.outer", + }, + goto_previous_end = { + ["[F"] = "@function.outer", + ["[C"] = "@class.outer", + }, + }, + swap = { + enable = true, + swap_next = { + ["sp"] = "@parameter.inner", + }, + swap_previous = { + ["sP"] = "@parameter.inner", + }, + }, + }, +}) +``` + +--- + +### ~/.config/nvim/lua/plugins/telescope.lua + +Telescope fuzzy finder configuration. + +```lua +local telescope = require("telescope") +local actions = require("telescope.actions") + +telescope.setup({ + defaults = { + prompt_prefix = " ", + selection_caret = " ", + path_display = { "truncate" }, + sorting_strategy = "ascending", + layout_strategy = "horizontal", + layout_config = { + horizontal = { + prompt_position = "top", + preview_width = 0.55, + results_width = 0.8, + }, + vertical = { + mirror = false, + }, + width = 0.87, + height = 0.80, + preview_cutoff = 120, + }, + mappings = { + i = { + [""] = actions.cycle_history_next, + [""] = actions.cycle_history_prev, + [""] = actions.move_selection_next, + [""] = actions.move_selection_previous, + [""] = actions.close, + [""] = actions.move_selection_next, + [""] = actions.move_selection_previous, + [""] = actions.select_default, + [""] = actions.select_horizontal, + [""] = actions.select_vertical, + [""] = actions.select_tab, + [""] = actions.preview_scrolling_up, + [""] = actions.preview_scrolling_down, + }, + n = { + [""] = actions.close, + [""] = actions.select_default, + [""] = actions.select_horizontal, + [""] = actions.select_vertical, + [""] = actions.select_tab, + ["j"] = actions.move_selection_next, + ["k"] = actions.move_selection_previous, + ["H"] = actions.move_to_top, + ["M"] = actions.move_to_middle, + ["L"] = actions.move_to_bottom, + ["gg"] = actions.move_to_top, + ["G"] = actions.move_to_bottom, + [""] = actions.preview_scrolling_up, + [""] = actions.preview_scrolling_down, + }, + }, + }, + pickers = { + find_files = { + theme = "dropdown", + previewer = false, + }, + live_grep = { + theme = "ivy", + }, + buffers = { + theme = "dropdown", + previewer = false, + }, + }, +}) + +-- Load telescope extensions +pcall(telescope.load_extension, "fzf") + +-- Telescope keybindings +local builtin = require("telescope.builtin") +vim.keymap.set("n", "ff", builtin.find_files, { desc = "Find files" }) +vim.keymap.set("n", "fg", builtin.live_grep, { desc = "Live grep" }) +vim.keymap.set("n", "fb", builtin.buffers, { desc = "Find buffers" }) +vim.keymap.set("n", "fh", builtin.help_tags, { desc = "Help tags" }) +vim.keymap.set("n", "fr", builtin.oldfiles, { desc = "Recent files" }) +vim.keymap.set("n", "fc", builtin.grep_string, { desc = "Grep string under cursor" }) +vim.keymap.set("n", "fd", builtin.diagnostics, { desc = "Find diagnostics" }) +``` + +--- + +### ~/.config/nvim/lua/plugins/nvimtree.lua + +File tree configuration. + +```lua +require("nvim-tree").setup({ + on_attach = function(bufnr) + local api = require("nvim-tree.api") + + local function opts(desc) + return { desc = "nvim-tree: " .. desc, buffer = bufnr, noremap = true, silent = true, nowait = true } + end + + vim.keymap.set("n", "", api.node.open.edit, opts("Open")) + vim.keymap.set("n", "", api.node.open.preview, opts("Open Preview")) + vim.keymap.set("n", ">", api.node.navigate.sibling.next, opts("Next Sibling")) + vim.keymap.set("n", "<", api.node.navigate.sibling.prev, opts("Previous Sibling")) + vim.keymap.set("n", ".", api.node.run.cmd, opts("Run Command")) + vim.keymap.set("n", "-", api.tree.change_root_to_parent, opts("Up")) + vim.keymap.set("n", "a", api.fs.create, opts("Create File")) + vim.keymap.set("n", "bd", api.node.mbx.trash, opts("Trash")) + vim.keymap.set("n", "bn", api.fs.rename, opts("Rename")) + vim.keymap.set("n", "bmv", api.fs.rename_basename, opts("Rename: Basename")) + vim.keymap.set("n", "bt", api.fs.copy.node_to_clipboard, opts("Copy To Clipboard")) + vim.keymap.set("n", "bp", api.fs.paste_from_clipboard, opts("Paste From Clipboard")) + vim.keymap.set("n", "q", api.tree.close, opts("Close")) + vim.keymap.set("n", "R", api.tree.reload, opts("Refresh")) + vim.keymap.set("n", "f", api.live_filter.start, opts("Filter")) + vim.keymap.set("n", "F", api.live_filter.clear, opts("Clean Filter")) + vim.keymap.set("n", "g?", api.tree.toggle_help, opts("Help")) + vim.keymap.set("n", "W", api.tree.collapse_all, opts("Collapse")) + vim.keymap.set("n", "E", api.tree.expand_all, opts("Expand All")) + vim.keymap.set("n", "S", api.node.search.manual, opts("Search")) + vim.keymap.set("n", "U", api.tree.toggle_custom_filter, opts("Toggle Filter")) + vim.keymap.set("n", "]", api.node.navigate.diagnostics.next, opts("Next Diagnostic")) + vim.keymap.set("n", "[", api.node.navigate.diagnostics.prev, opts("Prev Diagnostic")) + end, + sort_by = "case_sensitive", + view = { + width = 30, + hide_root_folder = false, + side = "left", + number = false, + relativenumber = false, + signcolumn = "yes", + }, + renderer = { + group_empty = true, + indent_width = 1, + indent_markers = { + enable = true, + inline_arrows = true, + icons = { + corner = "└", + edge = "│", + item = "│", + bottom = "─", + none = " ", + }, + }, + icons = { + webdev_colors = true, + git_placement = "after", + padding = " ", + symlink_arrow = " ➛ ", + show = { + file = true, + folder = true, + folder_arrow = true, + git = true, + }, + glyphs = { + default = " ", + symlink = "S", + bookmark = "B", + folder = { + arrow_closed = "▸", + arrow_open = "▾", + default = "D", + open = "D", + empty = "E", + empty_open = "E", + symlink = "S", + symlink_open = "S", + }, + git = { + unstaged = "✗", + staged = "✓", + unmerged = "✦", + renamed = "➜", + untracked = "★", + ignored = "◌", + }, + }, + }, + }, + filters = { + dotfiles = false, + git_clean = false, + no_buffer = false, + custom = { "node_modules", ".cache", "__pycache__" }, + exclude = {}, + }, + actions = { + use_system_clipboard = true, + change_dir = { + enable = true, + global = false, + restrict_above_cwd = false, + }, + file_popup = { + open_win_config = { + col = 1, + row = 1, + relative = "cursor", + border = "shadow", + style = "minimal", + }, + }, + open_file = { + quit_on_open = false, + resize_window = true, + window_picker = { + enable = true, + chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", + exclude = { + filetype = { "notify", "packer", "qf", "diff", "fugitive", "Outline" }, + buftype = { "terminal", "help" }, + }, + }, + }, + remove_file = { + close_buffer = true, + }, + }, + trash = { + cmd = "trash", + }, +}) + +-- Nvim-tree keybindings +vim.keymap.set("n", "e", ":NvimTreeToggle", { desc = "Toggle file tree" }) +vim.keymap.set("n", "o", ":NvimTreeFocus", { desc = "Focus file tree" }) +``` + +--- + +### ~/.config/nvim/lua/plugins/cmp.lua + +Autocomplete configuration. + +```lua +local cmp = require("cmp") +local luasnip = require("luasnip") + +require("luasnip.loaders.from_vscode").lazy_load() + +local has_words_before = function() + local line, col = unpack(vim.api.nvim_win_get_cursor(0)) + return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil +end + +cmp.setup({ + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end, + }, + mapping = cmp.mapping.preset.insert({ + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.abort(), + [""] = cmp.mapping.confirm({ select = true }), + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_jumpable() then + luasnip.expand_or_jump() + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, { "i", "s" }), + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, { "i", "s" }), + }), + sources = cmp.config.sources({ + { name = "nvim_lsp" }, + { name = "luasnip" }, + { name = "path" }, + }, { + { name = "buffer", keyword_length = 3 }, + }), + formatting = { + fields = { "kind", "abbr", "menu" }, + format = function(entry, vim_item) + local kind_icons = { + Text = "󰉿", + Method = "󰆧", + Function = "󰊕", + Constructor = "", + Field = "󰇽", + Variable = "󰀡", + Class = "󰠱", + Interface = "", + Module = "", + Property = "󰜢", + Unit = "󰑭", + Value = "󰎠", + Enum = "", + Keyword = "󰌋", + Snippet = "", + Color = "󰏘", + File = "󰈙", + Reference = "󰈇", + Folder = "󰉋", + EnumMember = "", + Constant = "󰏿", + Struct = "󰙅", + Event = "", + Operator = "󰆕", + TypeParameter = "", + } + vim_item.kind = string.format("%s %s", kind_icons[vim_item.kind], vim_item.kind) + vim_item.menu = ({ + nvim_lsp = "[LSP]", + luasnip = "[Snip]", + buffer = "[Buf]", + path = "[Path]", + })[entry.source.name] + return vim_item + end, + }, + window = { + completion = cmp.config.window.bordered(), + documentation = cmp.config.window.bordered(), + }, +}) + +-- Command line completion +cmp.setup.cmdline(":", { + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources({ + { name = "path" }, + }, { + { name = "cmdline" }, + }), +}) + +cmp.setup.cmdline("/", { + mapping = cmp.mapping.preset.cmdline(), + sources = { + { name = "buffer" }, + }, +}) +``` + +--- + +### ~/.config/nvim/lua/plugins/toggleterm.lua + +Integrated terminal configuration. + +```lua +require("toggleterm").setup({ + size = function(term) + if term.direction == "horizontal" then + return 15 + elseif term.direction == "vertical" then + return vim.o.columns * 0.4 + end + end, + open_mapping = [[]], + hide_numbers = true, + shade_filetypes = {}, + shade_terminals = true, + shading_factor = 2, + start_in_insert = true, + insert_mappings = true, + terminal_mappings = true, + persist_size = true, + direction = "float", + close_on_exit = true, + shell = vim.o.shell, + float_opts = { + border = "curved", + winblend = 0, + highlights = { + border = "Normal", + background = "Normal", + }, + }, +}) + +-- Terminal keybindings +local Terminal = require("toggleterm.terminal").Terminal + +local lazygit = Terminal:new({ + cmd = "lazygit", + hidden = true, + direction = "float", + float_opts = { + border = "curved", + }, +}) + +function _lazygit_toggle() + lazygit:toggle() +end + +vim.keymap.set("n", "gg", "lua _lazygit_toggle()", { desc = "Toggle lazygit" }) +vim.keymap.set("n", "tf", "ToggleTerm direction=float", { desc = "Toggle float terminal" }) +vim.keymap.set("n", "th", "ToggleTerm direction=horizontal", { desc = "Toggle horizontal terminal" }) +vim.keymap.set("n", "tv", "ToggleTerm direction=vertical", { desc = "Toggle vertical terminal" }) +``` + +--- + +### ~/.config/nvim/lua/plugins/formatter.lua + +Formatter and linter configuration using none-ls. + +```lua +local null_ls = require("null-ls") +local formatting = null_ls.builtins.formatting +local diagnostics = null_ls.builtins.diagnostics + +null_ls.setup({ + debug = false, + sources = { + -- Python + formatting.black, + formatting.isort, + diagnostics.pylint, + diagnostics.mypy, + + -- Shell + formatting.shfmt, + diagnostics.shellcheck, + + -- Lua + formatting.stylua, + + -- JavaScript/TypeScript + formatting.prettier, + formatting.eslint_d, + + -- JSON/YAML + formatting.jsonlint, + formatting.yamllint, + }, + on_attach = function(client, bufnr) + if client.supports_method("textDocument/formatting") then + vim.keymap.set("n", "f", function() + vim.lsp.buf.format({ async = false }) + end, { buffer = bufnr, desc = "Format buffer" }) + end + end, +}) + +-- Formatter keybindings +vim.keymap.set("n", "f", vim.lsp.buf.format, { desc = "Format buffer" }) +``` + +--- + +## Installing Language Servers + +After launching Neovim for the first time with this configuration: + +1. Open Neovim: `nvim` +2. Wait for lazy.nvim to install all plugins (this may take a few minutes) +3. After plugins are installed, install language servers: + - Press `ms` to open Mason (or run `:Mason`) + - Install the following: + - `pyright` (Python) + - `bash-language-server` (Shell/Bash) + - `lua-language-server` (Lua) + - `html-lsp` (HTML) + - `json-lsp` (JSON) + - `prettier` (Formatting) + - `shellcheck` (Shell linting) + - `shfmt` (Shell formatting) + - `black` (Python formatting) + - `mypy` (Python type checking) + +--- + +## Keybindings Reference + +### General +| Keybinding | Action | +|------------|--------| +| `` | Leader key | +| `h` | Clear search highlights | +| `w` | Save file | +| `q` | Quit | +| `tn` | Toggle line numbers | +| `tr` | Toggle relative numbers | + +### Window Navigation +| Keybinding | Action | +|------------|--------| +| `` | Navigate left | +| `` | Navigate down | +| `` | Navigate up | +| `` | Navigate right | +| `` | Resize window up | +| `` | Resize window down | +| `` | Resize window left | +| `` | Resize window right | + +### Telescope (Fuzzy Finder) +| Keybinding | Action | +|------------|--------| +| `ff` | Find files | +| `fg` | Live grep | +| `fb` | Find buffers | +| `fh` | Help tags | +| `fr` | Recent files | +| `fc` | Grep string under cursor | +| `fd` | Find diagnostics | + +### NvimTree (File Tree) +| Keybinding | Action | +|------------|--------| +| `e` | Toggle file tree | +| `o` | Focus file tree | + +### LSP +| Keybinding | Action | +|------------|--------| +| `gd` | Go to definition | +| `gD` | Go to declaration | +| `gi` | Go to implementation | +| `gr` | Go to references | +| `K` | Hover | +| `rn` | Rename | +| `ca` | Code actions | +| `e` | Show diagnostics | +| `[d` | Previous diagnostic | +| `]d` | Next diagnostic | + +### Debugging (DAP) +| Keybinding | Action | +|------------|--------| +| `db` | Toggle breakpoint | +| `dc` | Continue | +| `ds` | Step over | +| `di` | Step into | +| `do` | Step out | +| `dr` | Open REPL | +| `dl` | Run last debug config | +| `du` | Toggle DAP UI | + +### Terminal +| Keybinding | Action | +|------------|--------| +| `` | Toggle terminal | +| `tf` | Toggle float terminal | +| `th` | Toggle horizontal terminal | +| `tv` | Toggle vertical terminal | +| `gg` | Toggle lazygit | + +### Treesitter (Textobjects) +| Keybinding | Action | +|------------|--------| +| `af` | Select function (outer) | +| `if` | Select function (inner) | +| `ac` | Select class (outer) | +| `ic` | Select class (inner) | +| `aa` | Select parameter (outer) | +| `ia` | Select parameter (inner) | + +--- + +## First Launch + +1. **Launch Neovim:** + ```bash + nvim + ``` + +2. **Wait for plugin installation:** + - Lazy.nvim will automatically install all plugins + - You'll see progress in the statusline + +3. **Install language servers:** + - Run `:Mason` or press `ms` + - Install the servers listed above + +4. **Verify installation:** + - For Python: Open a `.py` file and run `:LspInfo` + - Run `:checkhealth` to see overall status + +5. **Optional: Install additional tools:** + ```bash + # For Python debugging + pip install debugpy + + # For shell linting + pip install shellcheck-py + + # For lazygit (optional but recommended) + brew install lazygit # macOS + sudo apt install lazygit # Ubuntu + ``` + +--- + +## Troubleshooting + +### LSP not starting +- Run `:LspInfo` to check LSP status +- Make sure language servers are installed via Mason + +### Treesitter highlighting not working +- Run `:TSUpdate` to update/install parsers +- Check `:TSInstallInfo` for available parsers + +### Telescope not working +- Ensure `ripgrep` is installed +- Check telescope log with `:Telescope log` + +### DAP not connecting +- Ensure `debugpy` is installed: `pip install debugpy` +- Check `: DapLog` for debug logs + +### Performance issues +- Check startup time with `:StartupTime` +- Disable unused plugins in `lua/plugins/init.lua` + +--- + +This guide provides a complete Neovim IDE setup. Modify the configuration files to suit your preferences! diff --git a/sync-at-home.sh b/sync-at-home.sh new file mode 100644 index 0000000..2c72def --- /dev/null +++ b/sync-at-home.sh @@ -0,0 +1 @@ +unison "$HOME/nextcloud/Notes/IT-Know-How/" "$HOME/Dokumente/01 Notizen/it-know-how/"