19 KiB
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:
/home/max/
├── Documents/
├── Downloads/
├── Projects/
│ ├── website/
│ ├── python-tool/
│ └── homelab/
Oder eine nach Git-Hosting strukturierte Variante:
~/src/
├── github.com/
│ └── benutzer/
│ ├── projekt1/
│ └── projekt2/
└── private/
Verzeichnis anlegen:
mkdir -p ~/Projects
oder
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:
find . -name "*.tmp" -delete
Erst suchen, dann löschen (empfohlen)
Dateien anzeigen:
find . -name "*.tmp"
Anschließend löschen:
find . -name "*.tmp" -delete
Mit Rückfrage löschen
find . -name "*.tmp" -ok rm {} \;
oder
find . -name "*.tmp" -exec rm -i {} \;
Nach Alter löschen
Logdateien, die älter als 30 Tage sind:
find . -name "*.log" -mtime +30 -delete
Leere Verzeichnisse löschen
find . -type d -empty -delete
Achtung
-delete löscht Dateien sofort und ohne Papierkorb.
Deshalb empfiehlt sich immer:
findohne-delete- Ergebnisse prüfen
-deleteergänzen
Beispiel:
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:
echo "a.txt b.txt c.txt" | xargs rm
Das entspricht:
rm a.txt b.txt c.txt
Typischer Einsatz mit find
Ohne xargs:
find . -name "*.log" -exec rm {} \;
Mit xargs:
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:
Meine Datei.txt
Dann liefert:
find . -name "*.txt" | xargs rm
xargs trennt standardmäßig an Leerzeichen und Zeilenumbrüchen.
Es interpretiert:
./Meine Datei.txt
als zwei Argumente:
./MeineDatei.txt
Das führt zu Fehlern.
Die sichere Lösung
Deshalb verwendet man fast immer:
find . -name "*.txt" -print0 | xargs -0 rm
Warum?
find -print0trennt Dateinamen mit einem Nullbyte (\0)xargs -0liest genau dieses Format
Dadurch funktionieren auch Dateinamen mit:
- Leerzeichen
- Tabs
- Zeilenumbrüchen
- Sonderzeichen
Platzhalter mit -I
Soll der Dateiname mitten im Befehl stehen:
find . -name "*.jpg" | xargs -I {} cp {} /backup/
Für jede Datei wird ausgeführt:
cp datei.jpg /backup/
Anzahl der Argumente begrenzen
seq 1 10 | xargs -n 3 echo
Ausgabe:
1 2 3
4 5 6
7 8 9
10
-n 3 bedeutet: maximal drei Argumente pro Befehlsaufruf.
Parallelisierung
Mehrere Prozesse gleichzeitig starten:
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:
find . -name "*.log" -exec rm {} +
Das erreicht nahezu denselben Effekt wie:
find . -name "*.log" -print0 | xargs -0 rm
Merksätze
Projekte
- Eigene Projekte →
~/Projectsoder~/src - Gemeinsame Projekte →
/srv - Installierte Software →
/opt
find
-
Dateien suchen:
find . -name "*.txt" -
Direkt löschen:
find . -name "*.txt" -delete
xargs
- Macht aus Pipe-Ausgabe Befehlsargumente.
- Spart viele einzelne Programmaufrufe.
- Immer sicher verwenden mit:
find . -print0 | xargs -0 <befehl>
Moderne Alternative
Wenn möglich:
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,/usr/share/snmp/mibs</mark>. - MIB nicht per
-moder Konfiguration aktiviert. Test:snmpwalk -m ALL ...oder in~/.snmp/snmp.confbzw./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:snmptranslate -M+/pfad -m ALL -Dparse-mibs OID
Parse-/Syntaxfehler in der MIB
-
Diagnose:
snmptranslate -Le -m ALL -M /pfad -On MEIN-MIB::objektFehler 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
snmptranslate -m +MEIN-MIB -IR meinObjekt→ gibt es einen Treffer?snmptranslate -Le -M /pfad/zu/mibs -m ALL .1.3.6.1.4.1.<enterprise>→ Fehler beim Laden?- 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):
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)
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.0mit „Unknown Object Identifier", ist die MIB nicht geladen → mit-m +MEIN-MIBbzw.-M /pfadergä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
dpkg -l | grep '^ii php8.2' | awk '{print $2}' | sed 's/8.2/8.4/'
Update der entsprechenden Pakete
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
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 )
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
openssl req -new -key server.key -out server.csr -config config.req
Muster für ein Config-File
[ 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
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
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/passwdenthält allgemeine Informationen über Benutzerkonten. -
/etc/shadowenthält sensible Informationen zur Passwort- und Accountverwaltung.
1. /etc/passwd
Die Datei /etc/passwd enthält pro Benutzer eine Zeile.
Beispiel
max:x:1001:1001:Max Mustermann:/home/max:/bin/bash
Die einzelnen Felder werden durch einen Doppelpunkt (:) getrennt.
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
max
Der eindeutige Name, unter dem der Benutzer im System bekannt ist.
Feld 2 – Passwort-Platzhalter
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
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:
0
Feld 4 – GID
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
Max Mustermann
Dieses Feld kann zusätzliche Informationen über den Benutzer enthalten, beispielsweise:
-
vollständiger Name
-
Raumnummer
-
Telefonnummer
-
sonstige Informationen
Feld 6 – Home-Verzeichnis
/home/max
Das Home-Verzeichnis des Benutzers.
Nach einem normalen Login befindet sich der Benutzer üblicherweise in diesem Verzeichnis.
Feld 7 – Login-Shell
/bin/bash
Die Shell, die nach einem Login gestartet werden soll.
Beispiele:
/bin/bash
/bin/sh
/bin/zsh
Bei Systemkonten findet man häufig auch:
/usr/sbin/nologin
oder:
/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
max:$6$...:20680:0:99999:7:::
Eine Zeile besteht aus 9 Feldern:
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:
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:
$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:
max:!!:20680:0:99999:7:::
Hier steht im zweiten Feld:
!!
!! 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:
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:
max:$6$...:20680:0:99999:7:::
Hier bedeuten die Werte:
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:
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
max:x:1001:1001:Max Mustermann:/home/max:/bin/bash
/etc/shadow
max:!!:20680:0:99999:7:::
Beide Einträge gehören über den Benutzernamen max zusammen.
Zusammengefasst:
/etc/passwd
│
├── Benutzername
├── UID
├── GID
├── Home-Verzeichnis
└── Login-Shell
/etc/shadow
│
├── Benutzername
├── Passwort-Hash / Passwortstatus
├── Passwortalter
├── Warnzeit
└── Account-Ablauf
Merksatz
/etc/passwdbeschreibt den Benutzer,/etc/shadowbeschreibt vor allem seinen Passwort- und Ablaufstatus.