# Linux: Projekte ablegen, Dateien suchen/löschen und `xargs` ## Projekte unter Linux organisieren Es gibt keine feste Vorgabe, aber einige Verzeichnisstrukturen haben sich etabliert. ### Für persönliche Entwicklungsprojekte Empfohlen: - `~/Projects/` - `~/Code/` - `~/src/` (unter Entwicklern sehr verbreitet) Beispiel: ```text /home/max/ ├── Documents/ ├── Downloads/ ├── Projects/ │ ├── website/ │ ├── python-tool/ │ └── homelab/ ``` Oder eine nach Git-Hosting strukturierte Variante: ```text ~/src/ ├── github.com/ │ └── benutzer/ │ ├── projekt1/ │ └── projekt2/ └── private/ ``` Verzeichnis anlegen: ```bash mkdir -p ~/Projects ``` oder ```bash mkdir -p ~/src ``` ### Für mehrere Benutzer | Verzeichnis | Zweck | | ----------------- | ----------------------------------------------------------------- | | `/srv/` | Gemeinsam genutzte Projekte oder Dienste | | `/usr/local/src/` | Systemweiter Quellcode | | `/opt/` | Installierte Drittanbieter-Software (nicht für eigenen Quellcode) | --- # Dateien mit `find` suchen und löschen ## Dateien nach Namen löschen Alle `.tmp`-Dateien löschen: ```bash find . -name "*.tmp" -delete ``` --- ## Erst suchen, dann löschen (empfohlen) Dateien anzeigen: ```bash find . -name "*.tmp" ``` Anschließend löschen: ```bash find . -name "*.tmp" -delete ``` --- ## Mit Rückfrage löschen ```bash find . -name "*.tmp" -ok rm {} \; ``` oder ```bash find . -name "*.tmp" -exec rm -i {} \; ``` --- ## Nach Alter löschen Logdateien, die älter als 30 Tage sind: ```bash find . -name "*.log" -mtime +30 -delete ``` --- ## Leere Verzeichnisse löschen ```bash find . -type d -empty -delete ``` --- ## Achtung `-delete` löscht Dateien sofort und ohne Papierkorb. Deshalb empfiehlt sich immer: 1. `find` ohne `-delete` 2. Ergebnisse prüfen 3. `-delete` ergänzen Beispiel: ```bash find ~/Downloads -name "*.zip" find ~/Downloads -name "*.zip" -delete ``` --- # xargs erklärt ## Was macht `xargs`? `xargs` nimmt Eingaben (meist aus einer Pipe) entgegen und macht daraus Argumente für einen anderen Befehl. Beispiel: ```bash echo "a.txt b.txt c.txt" | xargs rm ``` Das entspricht: ```bash rm a.txt b.txt c.txt ``` --- ## Typischer Einsatz mit `find` Ohne `xargs`: ```bash find . -name "*.log" -exec rm {} \; ``` Mit `xargs`: ```bash find . -name "*.log" | xargs rm ``` `xargs` bündelt mehrere Dateinamen zu einem einzigen `rm`-Aufruf und ist dadurch oft effizienter. --- ## Problem mit Leerzeichen Angenommen, es gibt eine Datei: ```text Meine Datei.txt ``` Dann liefert: ```bash find . -name "*.txt" | xargs rm ``` `xargs` trennt standardmäßig an Leerzeichen und Zeilenumbrüchen. Es interpretiert: ```text ./Meine Datei.txt ``` als zwei Argumente: - `./Meine` - `Datei.txt` Das führt zu Fehlern. --- ## Die sichere Lösung Deshalb verwendet man fast immer: ```bash find . -name "*.txt" -print0 | xargs -0 rm ``` ### Warum? - `find -print0` trennt Dateinamen mit einem Nullbyte (`\0`) - `xargs -0` liest genau dieses Format Dadurch funktionieren auch Dateinamen mit: - Leerzeichen - Tabs - Zeilenumbrüchen - Sonderzeichen --- ## Platzhalter mit `-I` Soll der Dateiname mitten im Befehl stehen: ```bash find . -name "*.jpg" | xargs -I {} cp {} /backup/ ``` Für jede Datei wird ausgeführt: ```bash cp datei.jpg /backup/ ``` --- ## Anzahl der Argumente begrenzen ```bash seq 1 10 | xargs -n 3 echo ``` Ausgabe: ```text 1 2 3 4 5 6 7 8 9 10 ``` `-n 3` bedeutet: maximal drei Argumente pro Befehlsaufruf. --- ## Parallelisierung Mehrere Prozesse gleichzeitig starten: ```bash find . -name "*.png" | xargs -P 4 -n 1 convert ``` Parameter: - `-P 4` → bis zu vier Prozesse parallel - `-n 1` → ein Dateiname pro Prozess --- ## Alternative ohne `xargs` Viele moderne Befehle unterstützen bereits mehrere Dateien gleichzeitig. Beispiel: ```bash find . -name "*.log" -exec rm {} + ``` Das erreicht nahezu denselben Effekt wie: ```bash find . -name "*.log" -print0 | xargs -0 rm ``` --- # Merksätze ### Projekte - Eigene Projekte → `~/Projects` oder `~/src` - Gemeinsame Projekte → `/srv` - Installierte Software → `/opt` ### `find` - Dateien suchen: ```bash find . -name "*.txt" ``` - Direkt löschen: ```bash find . -name "*.txt" -delete ``` ### `xargs` - Macht aus Pipe-Ausgabe Befehlsargumente. - Spart viele einzelne Programmaufrufe. - Immer sicher verwenden mit: ```bash find . -print0 | xargs -0 ``` ### Moderne Alternative Wenn möglich: ```bash find . -exec {} + ``` Diese Variante ist oft einfacher und ebenso effizient. # SNMP: MIB-Auflösung und OID-Übersetzung mit net-snmp ## OIDs werden trotz eingehängter MIB nicht textuell aufgelöst ### Mögliche Ursachen **MIB wird nicht geladen** - MIB liegt nicht in einem durchsuchten Verzeichnis. Prüfen mit `net-snmp-config --default-mibdirs`; übliche Pfade sind `~/.snmp/mibs`, `/usr/share/snmp/mibs`. - MIB nicht per `-m` oder Konfiguration aktiviert. Test: `snmpwalk -m ALL ...` oder in `~/.snmp/snmp.conf` bzw. `/etc/snmp/snmp.conf`: `mibs +MEIN-MIB`. - net-snmp lädt standardmäßig nur ein Minimalset. `mibs :` deaktiviert alles. **Dateiname passt nicht zum MIB-Namen** - net-snmp löst Module über den Dateinamen auf; der interne Modulname (vor `DEFINITIONS ::= BEGIN`) muss stimmen. **Fehlende IMPORTS / Abhängigkeiten** - Importierte MIBs (z. B. `SNMPv2-SMI`, `SNMPv2-TC`, herstellereigene Basis-MIBs) fehlen → Parsen schlägt still fehl. Sichtbar machen mit: ```bash snmptranslate -M+/pfad -m ALL -Dparse-mibs OID ``` **Parse-/Syntaxfehler in der MIB** - Diagnose: ```bash snmptranslate -Le -m ALL -M /pfad -On MEIN-MIB::objekt ``` Fehler werden auf stderr ausgegeben. **Numerische OID gehört zu keinem geladenen Zweig** - Die abgefragte Enterprise-OID liegt außerhalb dessen, was die MIB definiert (falsche/unvollständige MIB). ### Schneller Prüfweg 1. `snmptranslate -m +MEIN-MIB -IR meinObjekt` → gibt es einen Treffer? 2. `snmptranslate -Le -M /pfad/zu/mibs -m ALL .1.3.6.1.4.1.` → Fehler beim Laden? 3. Fehlende Import-MIBs nachlegen. Meist ist es eine fehlende Import-Abhängigkeit oder ein falscher Suchpfad/Modulname. --- ## Umgekehrt: von `MIB::objekt` auf die OID schließen Textuellen Namen statt numerischer OID übergeben (MIB muss geladen sein): ```bash snmpget -v2c -c public host MEIN-MIB::meinObjekt.0 snmpwalk -v2c -c public host MEIN-MIB::meinObjekt ``` ### Vorher ohne Gerät prüfen (Name → OID) ```bash snmptranslate -On MEIN-MIB::meinObjekt ``` `-On` erzwingt die numerische Ausgabe, also die zugehörige OID. Umgekehrt (OID → Name): ``` snmptranslate .1.3.6.1.4.1.xxx ``` ### Nützliche Varianten - Objektname allein suchen (ohne `MIB::`-Präfix): ``` snmptranslate -IR -On meinObjekt ``` - Vollständigen symbolischen Pfad anzeigen: ``` snmptranslate -Of MEIN-MIB::meinObjekt ``` - Objektdetails (Typ, Zugriff, Beschreibung): ``` snmptranslate -Td MEIN-MIB::meinObjekt ``` ### Hinweise - Scheitert `snmpget MEIN-MIB::meinObjekt.0` mit „Unknown Object Identifier", ist die MIB nicht geladen → mit `-m +MEIN-MIB` bzw. `-M /pfad` ergänzen. - Bei skalaren Objekten die `.0`-Instanz nicht vergessen. # Idoit von 35 auf 38 Test auf Masternode - kein main-Mode - ohne ansible ## php8.2 zu 8.4 8.2-Module ermitteln, die Ausgabe listet die entsprechenden 8.4-Paketnamen ```bash dpkg -l | grep '^ii php8.2' | awk '{print $2}' | sed 's/8.2/8.4/' ``` Update der entsprechenden Pakete ```bash apt update apt install -y $(dpkg -l | grep '^ii php8.2' | awk '{print $2}' | sed 's/8.2/8.4/') ``` Umschalten (mod_php/Apache) und CLI ```bash a2dismod php8.2 && a2enmod php8.4 crm res restart rcapache2 update-alternatives --set php /usr/bin/php8.4 ``` # Zertifikate ## Ein CSR (Certificate Signing Request) erstellen (bei vorhandenem ) ```bash openssl req -new -key server.key -out server.csr ``` Hier werden dann einige Daten abgefragt. Daher ist es einfacher mit einem Config-File das man mit übergibt ```bash openssl req -new -key server.key -out server.csr -config config.req ``` ### Muster für ein Config-File ```bash [ req ] default_bits = 4096 distinguished_name = req_distinguished_name req_extensions = req_cert_ext prompt = no default_days = 365 [ req_distinguished_name ] # # requested SubjectDN # C = DE O = Bund OU = Service CN = cmdb01.adm.ivbb.bund.de emailAddress = mail@bund.de [req_cert_ext] # subjectAltName = @alt_names ## requested SubjectAlternativeNames (SANs) [ alt_names ] DNS.1 = cmdb01.adm.ivbb.bund.de DNS.2 = mlseazcmd01.adm.ivbb.bund.de DNS.3 = mlsfazcmd01.adm.ivbb.bund.de ``` ## Betrachten des CSR ```bash openssl req -text -in ``` #### Notizen zu Zertifikate ##### Private Key erstellen openssl genrsa -out $HOME/servercrt/dlsea3tim01.server.key 2048 ##### Zertifikatsrequest erstellen openssl req -new -days 1095 -key dlsea3tim01.server.key -out dlsea3tim01.server.csr -config req_config.dlsea3tim01.adm.ivbb.bund.de ##### Zertifikatsrequest ansehen openssl req -text -in dlsea3tim01.server.csr|less Bei Apache/mod_ssl ist der Unterschied: - **`SSLCertificateFile`** → enthält das **öffentliche Zertifikat** des Servers. Darin stecken u. a. der öffentliche Schlüssel, Domainname und die Signatur der CA. Dieses Zertifikat wird beim TLS-Handshake an den Client geschickt. - **`SSLCertificateKeyFile`** → enthält den dazugehörigen **privaten Schlüssel**. Er bleibt ausschließlich auf dem Server und darf **niemals veröffentlicht** werden. # SCP ```bash scp [Optionen] [Quelle] [Ziel] ``` ### Optionen Dies sind optionale Flags, die das Verhalten des SCP-Befehls verändern. Sie können verschiedene Optionen verwenden, um den Übertragungsprozess individuell zu gestalten. Hier sind einige gängige Optionen: **-r:** Kopiert Verzeichnisse und deren Inhalte rekursiv. **-p:** Behält die Berechtigungen, Zeitstempel und Modi der Originaldatei bei. –**P**: Gibt die Portnummer für die SSH-Verbindung an. –**i**: Gibt die private Schlüsseldatei für die SSH-Authentifizierung an. **-C:** Verwenden Sie die Komprimierung, um die Datenübertragung zu beschleunigen. **-l:** Begrenzen Sie die für die Übertragung verwendete Bandbreite (in Kbit/s). **-v:** Ausführlicher Modus – zeigt Debugging-Meldungen während der Übertragung an. **-o:** Übergibt eine Option an den SSH-Client. Sie kann verwendet werden, um die strenge Prüfung des Hostschlüssels zu deaktivieren. # Linux: `/etc/passwd` und `/etc/shadow` Unter Linux werden Benutzerinformationen hauptsächlich in den Dateien `/etc/passwd` und `/etc/shadow` gespeichert. - `/etc/passwd` enthält allgemeine Informationen über Benutzerkonten. - `/etc/shadow` enthält sensible Informationen zur Passwort- und Accountverwaltung. --- ## 1. `/etc/passwd` Die Datei `/etc/passwd` enthält pro Benutzer eine Zeile. ### Beispiel ```text max:x:1001:1001:Max Mustermann:/home/max:/bin/bash ``` Die einzelnen Felder werden durch einen Doppelpunkt (`:`) getrennt. ```text max:x:1001:1001:Max Mustermann:/home/max:/bin/bash  │  │   │    │         │           │          │  │  │   │    │         │           │          └─ Login-Shell  │  │   │    │         │           └─ Home-Verzeichnis  │  │   │    │         └─ Kommentar / GECOS  │  │   │    └─ primäre GID  │  │   └─ UID  │  └─ Passwort-Platzhalter  └─ Benutzername ``` ### Aufbau | Feld | Beispiel | Bedeutung | |---|---|---| | 1 | `max` | Benutzername | | 2 | `x` | Passwort-Platzhalter | | 3 | `1001` | UID – User ID | | 4 | `1001` | GID – primäre Group ID | | 5 | `Max Mustermann` | Kommentar / GECOS | | 6 | `/home/max` | Home-Verzeichnis | | 7 | `/bin/bash` | Login-Shell | ### Feld 1 – Benutzername ```text max ``` Der eindeutige Name, unter dem der Benutzer im System bekannt ist. --- ### Feld 2 – Passwort-Platzhalter ```text x ``` Das `x` bedeutet, dass sich die eigentlichen Passwortinformationen in `/etc/shadow` befinden. Historisch konnten Passwort-Hashes direkt in `/etc/passwd` gespeichert werden. Das wäre heute problematisch, da `/etc/passwd` normalerweise für alle Benutzer lesbar sein muss. --- ### Feld 3 – UID ```text 1001 ``` Die **UID (User ID)** ist die numerische Kennung des Benutzers. Linux arbeitet intern an vielen Stellen mit der UID und nicht mit dem Benutzernamen. Beispielsweise besitzt `root` normalerweise die UID: ```text 0 ``` --- ### Feld 4 – GID ```text 1001 ``` Die **GID (Group ID)** gibt die primäre Gruppe des Benutzers an. Weitere Gruppenzugehörigkeiten werden normalerweise über `/etc/group` bzw. entsprechende Benutzerverwaltungsdienste bestimmt. --- ### Feld 5 – GECOS / Kommentar ```text Max Mustermann ``` Dieses Feld kann zusätzliche Informationen über den Benutzer enthalten, beispielsweise: - vollständiger Name - Raumnummer - Telefonnummer - sonstige Informationen --- ### Feld 6 – Home-Verzeichnis ```text /home/max ``` Das Home-Verzeichnis des Benutzers. Nach einem normalen Login befindet sich der Benutzer üblicherweise in diesem Verzeichnis. --- ### Feld 7 – Login-Shell ```text /bin/bash ``` Die Shell, die nach einem Login gestartet werden soll. Beispiele: ```text /bin/bash /bin/sh /bin/zsh ``` Bei Systemkonten findet man häufig auch: ```text /usr/sbin/nologin ``` oder: ```text /bin/false ``` Damit soll normalerweise ein interaktiver Login verhindert werden. --- # 2. `/etc/shadow` Die Datei `/etc/shadow` enthält die sensiblen Passwort- und Ablaufinformationen eines Benutzers. Sie ist deshalb im Gegensatz zu `/etc/passwd` normalerweise nur für `root` bzw. entsprechend privilegierte Prozesse lesbar. ### Beispiel ```text max:$6$...:20680:0:99999:7::: ``` Eine Zeile besteht aus **9 Feldern**: ```text max:$6$...:20680:0:99999:7:::  │      │      │   │    │   │ │ │ │  │      │      │   │    │   │ │ │ └─ reserviert  │      │      │   │    │   │ │ └─ Account-Ablauf  │      │      │   │    │   │ └─ Inaktivität  │      │      │   │    │   └─ Warnzeit  │      │      │   │    └─ maximales Passwortalter  │      │      │   └─ minimales Passwortalter  │      │      └─ letzte Passwortänderung  │      └─ Passwort-Hash / Passwortstatus  └─ Benutzername ``` ## Aufbau | Feld | Bedeutung | |---|---| | 1 | Benutzername | | 2 | Passwort-Hash / Passwortstatus | | 3 | Letzte Passwortänderung | | 4 | Minimales Passwortalter | | 5 | Maximales Passwortalter | | 6 | Warnzeit vor Passwortablauf | | 7 | Inaktivitätszeit | | 8 | Ablaufdatum des Accounts | | 9 | Reserviert | --- ## 3. Benutzername Das erste Feld muss zum entsprechenden Benutzerkonto passen. Beispiel: ```text max ``` Damit können die Informationen aus `/etc/passwd` und `/etc/shadow` demselben Benutzer zugeordnet werden. --- ## 4. Passwort-Hash / Passwortstatus Das zweite Feld ist besonders wichtig. Ein Eintrag könnte beispielsweise folgendermaßen aussehen: ```text $6$salt$hash ``` Dabei steht `$6$` bei klassischen `crypt`-Passwörtern für **SHA-512**. Auf modernen Linux-Systemen können auch andere Verfahren eingesetzt werden, beispielsweise **yescrypt**, das häufig an einem Präfix wie `$y$` erkennbar ist. Das Passwort selbst wird nicht gespeichert. Stattdessen wird ein daraus berechneter Hash gespeichert. --- ## 5. Besondere Werte im Passwortfeld Das zweite Feld kann auch Werte enthalten, die keinen gültigen Passwort-Hash darstellen. ### Übersicht | Eintrag | Typische Bedeutung | |---|---| | `$6$...` | Passwort-Hash, z. B. SHA-512 | | `$y$...` | Passwort-Hash, z. B. yescrypt | | `!$6$...` | Passwort gesperrt, ursprünglicher Hash noch vorhanden | | `!!` | Kein verwendbares Passwort gesetzt / Passwort-Login gesperrt | | `*` | Passwort-Authentifizierung nicht möglich | | leer | Potenziell kein Passwort erforderlich – sicherheitskritisch | --- # 6. Was bedeutet `!!`? Beispiel: ```text max:!!:20680:0:99999:7::: ``` Hier steht im zweiten Feld: ```text !! ``` `!!` ist **kein gültiger Passwort-Hash**. Es bedeutet typischerweise: > Für diesen Benutzer ist kein verwendbares lokales Passwort gesetzt. Eine Authentifizierung über dieses Passwortfeld ist daher nicht möglich. Das sieht man beispielsweise bei neu angelegten oder bewusst für Passwort-Logins gesperrten Accounts. Wichtig ist dabei: **Ein gesperrtes Passwort ist nicht automatisch dasselbe wie ein vollständig gesperrter Benutzeraccount.** Abhängig von der Systemkonfiguration könnten andere Authentifizierungsverfahren weiterhin funktionieren, beispielsweise: - SSH Public Keys - Kerberos - LDAP / zentrale Authentifizierung - SSO - andere PAM-basierte Verfahren Vereinfacht: ```text max:!!:20680:0:99999:7:::     ^^     │     └── kein gültiger Passwort-Hash         → lokale Passwortauthentifizierung nicht möglich ``` --- # 7. Passwortalter und Ablauf Die restlichen Felder von `/etc/shadow` steuern unter anderem die Gültigkeitsdauer eines Passworts. Beispiel: ```text max:$6$...:20680:0:99999:7::: ``` Hier bedeuten die Werte: ```text 20680 : 0 : 99999 : 7   │      │     │     │   │      │     │     └─ Warnung vor Ablauf   │      │     └─ maximales Passwortalter   │      └─ minimales Passwortalter   └─ letzte Passwortänderung ``` Die Datumswerte werden grundsätzlich als Anzahl der **Tage seit dem 01.01.1970** angegeben. --- # 8. Warum gibt es zwei Dateien? Der Grund für die Trennung ist hauptsächlich die Sicherheit. `/etc/passwd` muss von vielen Programmen gelesen werden können. Beispielsweise müssen Programme herausfinden können: ```text UID 1001 → Benutzer max ``` Daher ist `/etc/passwd` normalerweise für alle Benutzer lesbar. Passwort-Hashes sollen dagegen geschützt werden. Deshalb wurden sie in die stärker geschützte Datei `/etc/shadow` ausgelagert. --- # 9. Zusammenhang von `/etc/passwd` und `/etc/shadow` Für denselben Benutzer könnten die Einträge beispielsweise so aussehen: ### `/etc/passwd` ```text max:x:1001:1001:Max Mustermann:/home/max:/bin/bash ``` ### `/etc/shadow` ```text max:!!:20680:0:99999:7::: ``` Beide Einträge gehören über den Benutzernamen `max` zusammen. Zusammengefasst: ```text /etc/passwd      │      ├── Benutzername      ├── UID      ├── GID      ├── Home-Verzeichnis      └── Login-Shell /etc/shadow      │      ├── Benutzername      ├── Passwort-Hash / Passwortstatus      ├── Passwortalter      ├── Warnzeit      └── Account-Ablauf ``` ## Merksatz > **`/etc/passwd` beschreibt den Benutzer, `/etc/shadow` beschreibt vor allem seinen Passwort- und Ablaufstatus.**