1018 lines
19 KiB
Markdown
1018 lines
19 KiB
Markdown
# 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 <befehl>
|
||
```
|
||
|
||
### Moderne Alternative
|
||
|
||
Wenn möglich:
|
||
|
||
```bash
|
||
find . -exec <befehl> {} +
|
||
```
|
||
|
||
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`, <mark>`/usr/share/snmp/mibs</mark>`.
|
||
- 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.<enterprise>` → 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 <csr>
|
||
```
|
||
|
||
#### 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.**
|
||
|
||
###############
|
||
|
||
Änderungen an Profil-Dateien wie `~/.bashrc` erfordern eine neue Shell-Sitzung oder das explizite Ausführen von `source ~/.bashrc`, damit sie in der aktuellen Sitzung wirksam werden. |