Beispiele für die Nutzung des GNU-Werkzeugkastens
Einige der nachfolgend gezeigten Kommandos sind interne (eingebaute) Kommandos moderner Shells. Implizit wird immer die Nutzung der Bash unterstellt.
Hilfe:
# Manual-Seite des Kommandos chown aufschlagen man chown # Manual-Seite des Systemrufs chown aufschlagen # (Abschnitt 2 des Manuals) man 2 chown # GNU-Info-Seite des Kommandos chown aufschlagen info chown # Bash-Online-Hilfe für Kommando cd ausgeben help cd # Online-Hilfe der GNU-Tools (hier: Kommando rm) # durch Option --help aufrufen rm --help
eigene Identität / angemeldete Benutzer:
# eigene Identität ermitteln id # Informationen über lokal angemeldete Benutzer ermitteln w finger # Informationen über entfernt an host angemeldete Benutzer ermitteln; # funktioniert nur bei Zugriff auf den entfernten finger-Dämon finger @host
Ausgabe und Eingabe:
# drei Argumente unformatiert ausgeben echo 1 2 3 # drei Argumente formatiert ausgeben printf '%d: %d(%d)\n' 1 2 3 # Inhalt der Shell- und Umgebungs-Variablen PATH (Suchpfad) ausgeben echo $PATH # Ausgabe aller Dateinamen, die auf folgende Muster passen: # - Namen unter /etc, die mit p oder s beginnen # - Namen unter /etc, die mit Punkt und einem beliebigen Zeichen danach enden # - Namen unter /, die nicht mit einem Buchstaben aus dem Intervall a bis f beginnen # - Namen unter /usr/bin, die auf .sh enden echo /etc/{[ps]*,*.?} /[^a-f]* /usr/bin/*.sh # Datum ausgeben; Ausgabe des Kommandos date wird in das Argument # von echo eingefügt echo "Heute ist der $(date '+%d.%m.%Y')." # Zahl auf Variable zahl einlesen read -p 'Zahl: ' zahl # Zahlen ins Feld array einlesen read -p 'Feld: ' -a array # Feld array geschlossen ausgeben echo ${array[*]} # Feld array zeilenweise ausgeben for i in "${array[@]}" do echo "$i" done # erstes Element von Feld array ausgeben echo ${array[0]} echo $array # drittes Element von Feld array ausgeben echo ${array[2]}
Umgang mit Prozessen:
# alle root-Prozesse anzeigen ps auxww | grep '^root\b' # dito, nur in etwas anderem Format ps -ef | grep '^root\b' # Funktion psg definieren, die die Prozess-Liste nach einem # egrep-Muster durchsucht function psg() { ps auxww | egrep "$1" | fgrep -v "egrep $1" | fgrep -v "grep -E $1" } # Prozesse suchen, deren Einträge swap oder irq enthalten psg 'swap|irq' # Prozessbaum-Anzeige mit Prozess-ID und UID-Wechseln pstree -up # Prozess 324 mit Signal 9 (SIGKILL) hart beenden kill -9 324 # Signal 15 (SIGTERM) an alle Prozesse senden, die das # Kommando sleep ausführen killall sleep # Signal 2 (SIGINT) in der Shell abfangen trap 'echo SIGINT' 2 # dito trap 'echo SIGINT' SIGINT # Laufzeit und Status des Systems (Anzahl Nutzer, Last) anzeigen uptime # Echtzeit-Anzeige der Prozess-Liste (in Auszügen) und des System-Status top
Navigation im File-System:
pwd # absoluten Pfad des aktuellen Verzeichnisses anzeigen # Das interne pwd der Bash kennt einen logischen und physischen Modus. # Der physische Modus kann generell durch die set-Option -P oder spezifisch # durch die Option -P von pwd aktiviert werden. cd /tmp # Wechsel des aktuellen Verzeichnisses nach /tmp cd # Wechsel ins Home-Verzeichnis des aktuellen Benutzers cd ~max # Wechsel ins Home-Verzeichnis des Benutzers max cd .. # Wechsel ins Eltern-Verzeichnis cd - # Wechsel ins zuvor aktuelle Verzeichnis pushd / # aktuelles Verzeichnis im Directory-Stack merken und Wechsel nach / (Wurzel) pushd ~ # dito, aber Wechsel ins Home-Verzeichnis dirs -l -v # Anzeige des Directory-Stacks cd /etc # Wechsel nach /etc popd # letztes Verzeichnis des Directory-Stacks löschen und zum Verzeichnis # wechseln, das an der neuen Stack-Spitze steht
elementarer Umgang mit Dateien und Verzeichnissen:
ls # Inhalt des aktuellen Verzeichnisses im kurzen Format anzeigen ls -l # Inhalt des aktuellen Verzeichnisses im langen Format anzeigen ls -la # dito, aber zusätzlich die Punkt-Dateien anzeigen ls -ld # den Eintrag für das aktuelle Verzeichnis anzeigen ls -ld . # dito ls -ld .. # den Eintrag für das Eltern-Verzeichnis anzeigen alias l='ls -l' # Alias l als Abkürzung für ls -l definieren l /tmp # entspricht ls -l /tmp # Anzeige des Inhalts von /tmp im langen Format, umgekehrt nach der # Modifikationszeit geordnet (zuletzt modifizierte Files stehen am Ende der # Liste) ls -ltr /tmp # bei allen Files des aktuellen Verzeichnisses, deren Name auf .sh endet, # wird für Gruppe und Welt das Ausführungsrecht gesetzt chmod go+x *.sh chown otto abc # File abc bekommt den Eigentümer otto mkdir dir1 # Verzeichnis dir1 anlegen rmdir dir1 # (leeres) Verzeichnis dir1 löschen rm -rf dir1 # Verzeichnis dir1 rekursiv und ohne Rückfrage löschen less /etc/passwd # /etc/passwd mit dem Pager less anzeigen # die Ausgabe von find . (alle Verzeichniseinträge unterhalb des # aktuellen Verzeichnisses) mit dem Pager less anzeigen find . | less # alle symbolischen Links unterhalb von /etc im langen Format ausgeben und # in den Editor vim laden find /etc -type l -ls | vim - # die Namen aller Dateien unterhalb des aktuellen Verzeichnisses ermitteln # und über xargs an das Kommando md5sum weitergeben (berechnet die # MD5-Prüfsumme für alle Argumente); durch die korrespondierenden Optionen # -print0 und -0 können auch Dateinamen, die Leerräume (Whitespace-Zeichen # wie Leerzeichen und Newlines) enthalten und somit bei der Verarbeitung # in der Shell Probleme verursachen, sauber behandelt werden; # die Ausgabe von find (die Dateiliste) wird durch tee sowohl in der Datei # /tmp/filelist abgespeichert als auch über eine Pipe an xargs weitergegeben; # das Ergebnis von md5sum wird in der Datei /tmp/summen abgelegt find . -type f -print0 | tee /tmp/filelist | xargs -0 md5sum > /tmp/summen cp file kopie # kopiert Datei file nach kopie # 1:1-Kopie von src nach dst (Dateien oder Dateibäume, Erhalt aller # Attribute, kein automatisches Überschreiben existierender Dateien) cp -ia src dst mv file new # benennt file in new um mv file /tmp # verschiebt file nach /tmp mv file /tmp/new # verschiebt file nach /tmp/new ln -s file symlink # symbolischen Link symlink als Verweis auf file erzeugen rm file # löscht Datei oder Link file # die oben gespeicherte Dateiliste wird per Eingabe-Umlenkung an xargs # übergeben; dadurch wird rm -v für alle Dateien der Liste aufgerufen; # somit werden alle Dateien der Liste gelöscht; durch die Option v wird # die Löschung protokolliert xargs -0 rm -v < /tmp/filelist # Option dotglob aktivieren, so dass Dateinamens-Muster auch Dateinamen # einschließen, die mit einem Punkt beginnen (außer . und ..) shopt -s dotglob # alle Dateien des aktuellen Verzeichnisses mit Ausnahme der Datei myfile # löschen echo * | fgrep -v myfile | xargs rm -f # dito mit alternativer Realisierung unter Verwendung erweiterter Muster # (Aktivierung über shopt -s extglob) echo !(myfile) | xargs rm -f # alle Dateien des aktuellen Verzeichnisses, deren Namen mit p beginnen # und nicht auf 29 enden (wieder unter Verwendung erweiterter Muster) echo p!(*29) # Modifikationszeit von file auf die aktuelle Zeit setzen; leere Datei # file anlegen, falls sie bisher nicht existiert touch file # Inhalt von /etc/hosts auf die Standardausgabe ausgeben cat /etc/hosts # /etc/passwd und /etc/hosts verketten und Zeilen von hinten nach vorn # ausgeben cat /etc/{passwd,hosts} | tac # Name der Resultat-Datei /tmp/resultat.txt an die Shell-Variable # result zuweisen result=/tmp/resultat.txt # evtl. existierende Resultat-Datei stillschweigend löschen rm -f $result for file in /etc/{hosts,printcap} do # die Variable file durchläuft die Liste der Dateinamen /etc/hosts # und /etc/printcap echo $file >> $result # den aktuellen Dateinamen (Inhalt der Variable file) an die # Resultat-Datei anhängen cat $file >> $result # den Inhalt der durch file benannten Datei an die Resultat-Datei # anhängen echo ======== >> $result # Trennzeile an die Resultat-Datei anhängen done
Montieren/Demontieren von Dateisystemen:
# Dateisystem nach /media/floppy montieren; Ort des Dateisystems muss in der # Datei /etc/fstab angegeben sein mount /media/floppy # Dateisystem unter /dev/fd0 (Diskette) nach /media/floppy montieren mount /dev/fd0 /media/floppy # Dateisystem unter /media/floppy demontieren umount /media/floppy
Mtools: Arbeit mit MSDOS-Dateisystemen ohne Montieren/Demontieren:
# alle Dateien des aktuellen Verzeichnisses, deren Namen auf .sh enden, ins # aktuelle Verzeichnis (standardmäßig die Wurzel) von Laufwerk A: (Diskette) kopieren mcopy *.sh a: # alle Dateien und Unterverzeichnisse des Verzeichnisses DISKETTE unterhalb # des Home-Verzeichnisses ins aktuelle Verzeichnis von Laufwerk A: kopieren mcopy ~/DISKETTE/* a: # Wenn man aktuell im Linux-Home-Verzeichnis steht, kann man kurz # mcopy DISKETTE/* a: # schreiben. # alle Dateien des aktuellen Verzeichnisses der Diskette in Laufwerk A: # ins aktuelle Verzeichnis kopieren mcopy a: mcopy a: . # die explizite Angabe des Ziel-Verzeichnisses . ist optional mcopy -v a: # Option -v protokolliert die kopierten Dateien auf die # Standard-Fehlerausgabe (vorzugsweise also auf den Bildschirm) # eine analoge Kopie in ein benanntes Verzeichnis mcopy a: ~/DISKETTE # kopiert ins Verzeichnis DISKETTE unterhalb des Home-Verzeichnisses mcopy a: /tmp # kopiert ins Verzeichnis /tmp # alle Dateien, deren Namen auf .sh enden, im aktuellen Verzeichnis von # Laufwerk A: (Diskette) löschen mdel a:\*.sh # Inhalt des aktuellen Verzeichnisses von A: anzeigen mdir # aktuelles MTOOLS-Verzeichnis nach A:/DATEN wechseln mcd a:/DATEN # aktuelles MTOOLS-Verzeichnis anzeigen mcd # Diskette in Laufwerk A: logisch formatieren (leeres Dateisystem erzeugen); # dies gestattet ein sehr schnelles Löschen des Disketteninhalts, da keine # physische Formatierung der Spuren erfolgt mformat a:
Textanalyse/-manipulation:
# Datei /etc/passwd mit dem interaktiven Editor Vim öffnen vim /etc/passwd # mit dem nicht-interaktiven Stream-Editor sed Kommentare und Leerzeilen # aus der Datei /etc/services löschen und Ergebnis auf die Standard-Ausgabe # ausgeben sed -e 's/#.*//' -e '/^$/d' /etc/services # die Datei /etc/passwd nach /tmp kopieren und dort mit dem Zeilen-Editor ed # bearbeiten; diesem wird mittels printf über die Standard-Eingabe die abzuarbeitende # Kommandofolge übergeben; er soll in den Zeilen 60 bis 100 jede am Zeilenende # vorkommende Zeichenfolge bash durch zsh ersetzen und das Ergebnis in das # Ausgangs-File zurückspeichern cp /etc/passwd /tmp && printf '60,100 s/bash$/zsh\nwq\n' | ed /tmp/passwd &> /dev/null
# sucht die Zeile(n) in /etc/passwd, die mit otto: beginnen grep '^otto:' /etc/passwd # sucht die Zeile(n) in /etc/passwd, die mit otto: oder not: beginnen egrep '^(otto|not):' /etc/passwd # ermittelt die Namen aller Dateien unterhalb des Verzeichnisses # dir1, in denen die Zeichenkette xyz vorkommt grep -rl xyz dir1 # ermittelt die Namen aller Dateien unterhalb des Verzeichnisses # dir1, in denen die Zeichenkette xyz nicht vorkommt grep -rL xyz dir1 # ermittelt die Namen derjenigen lesbaren Dateien im Verzeichnis /etc, die # irgendwo einen Punkt enthalten find /etc -type f -maxdepth 1 | xargs fgrep -l . 2>/dev/null # sortiert den Inhalt von /etc/passwd nach der UID (Feld 3) numerisch # fallend und speichert das Ergebnis in /tmp/passwd sort -t: -k3,3 -rn /etc/passwd > /tmp/passwd # dito, aber das Ergebnis erscheint zusätzlich auf der Standard-Ausgabe, wo # aber nur die ersten 20 Zeilen angezeigt werden sort -t: -k3,3 -rn /etc/passwd | tee /tmp/passwd | head -20
# zeigt die Differenz zwischen den beiden Dateien file.bak und file im # Format "unified context" an diff -u file.bak file # ermittelt rekursiv die Differenz zwischen den beiden Verzeichnissen # dir.old und dir.new; die Ausgabe erfolgt wieder im Format "unified # context" diff -ru dir.old dir.new
# findet alle Dateien ab dem aktuellen Verzeichnis, die höchstwahrscheinlich # mehrfach identisch vorkommen; mit find wird die Liste aller Dateien # erstellt; durch die korrespondierenden Optionen -print0 von # find und -0 von xargs werden auch File-Namen mit Leer- # und Sonderzeichen korrekt behandelt; für alle ermittelten Dateien wird die # 32 Zeichen lange externe Repräsentation der MD5-Summe errechnet; die Liste # wird nach dieser Summe sortiert; mittels uniq -D werden alle # Einträge der Liste ausgegeben, die mehrfach vorkommen; durch die Option # -w 32 betrachtet uniq nur die ersten 32 Zeichen jeder Zeile, # also die MD5-Summe und nicht den dahinter folgenden Dateinamen find . -type f -print0 | xargs -0 md5sum | sort | uniq -D -w 32
# ermittelt die Anzahl der Zeichen (Bytes) und Wörter der Datei # /etc/services wc -cw /etc/services # ermittelt die Anzahl der Verzeichnisse ab dem aktuellen Verzeichnis find . -type d | wc -l
# Ausgabe der ersten 5 Zeilen von /etc/passwd head -5 /etc/passwd # Ausgabe der letzten 10 Zeilen des Ring-Puffers des Linux-Kerns (enthält # Log-Informationen) dmesg | tail # durch das Ampersand am Ende wird folgende Schleife im Hintergrund # ausgeführt for ((i=0; i < 10; i++)) do # Zähl-Schleife, die 10 Mal durchlaufen wird; # einen aktuellen Zeitstempel an die Datei /tmp/file anhängen und # dann eine Sekunde schlafen date >> /tmp/file ; sleep 1 done & # dito mit alternativem Schleifenkopf (ab Bash 3) for i in {1..10} do date >> /tmp/file ; sleep 1 done & # kontinuierliche Anzeige des Datei-Endes von /tmp/file # (man kann ein Wachstum der Datei sehen) tail -f /tmp/file
# Feld 1 (Nutzerkennzeichen) der /etc/passwd ausgeben cut -d: -f1 /etc/passwd # Feld 1 (Nutzerkennzeichen) und Feld 3 (UID) der /etc/passwd durch # getrennte cut-Kommandos ermitteln und über das Kommando paste unter # Verwendung der Prozess-Substitution der Bash zeilenweise # zusammensetzen paste -d: <(cut -d: -f1 /etc/passwd) <(cut -d: -f3 /etc/passwd) # Das konkrete Beispiel ließe sich einfacher so schreiben: # cut -d: -f1,3 /etc/passwd
# alle Kleinbuchstaben durch die zugehörigen Großbuchstaben ersetzen echo abcde | tr a-z A-Z # dito echo abcde | tr [:lower:] [:upper:] # die Kleinbuchstaben a, b und c löschen echo abcdeabcde | tr -d a-c
# die Summe aller UIDs (Feld 3) der /etc/passwd bilden und ausgeben awk -F: ' { sum += $3 } END { print sum } ' /etc/passwd # der Variablen awk_file den Namen einer AWK-Datei zuweisen awk_file=/tmp/passwd.awk # ein AWK-Programm, das die einzelnen Felder der /etc/passwd # besser lesbar anzeigt, in die AWK-Datei schreiben echo ' # die Zeilen der /etc/passwd der Reihe nach ausgeben BEGIN { FS = ":" } { print "Eintrag", FNR print "name :", $1 print "password :", $2 print "uid :", $3 print "gid :", $4 print "real_name:", $5 print "home_dir :", $6 print "shell :", $7 print "======================" }' > $awk_file # AWK-Programm in der AWK-Datei ausführen; Resultat in die # Datei /tmp/passwd.out umlenken awk -f $awk_file /etc/passwd > /tmp/passwd.out # Ausgabe-Datei mit dem Editor Vim öffnen; # !$ entspricht dem letzten Wort der letzten Kommandozeile vim !$ # passwd-Zeile für Nutzer otto suchen und per Pipe an das obige # AWK-Programm übergeben grep ^otto: /etc/passwd | awk -f $awk_file
Komprimieren und Archivieren:
# Datei file mittels gzip komprimieren, danach das Resultat file.gz # wieder dekomprimieren und anschließend file mittels bzip2 nochmals # komprimieren (Resultat ist file.bz2) gzip file ; gunzip file.gz ; bzip2 file # Kompressions-Kommando im Hintergrund ausführen gzip file & # Liste der Hintergrund-Jobs anzeigen jobs # aktuellen Job in den Vordergrund holen fg # Vordergrund-Prozess suspendieren Ctrl-Z # und in den Hintergrund schicken bg # Job 1 beenden kill %1 # file.bz2 auf die Standard-Ausgabe dekomprimieren und Zeichen zählen bunzip2 -c file.bz2 | wc -c bzcat file.bz2 | wc -c # das komplette Verzeichnis dir rekursiv ins ZIP-Archiv archiv.zip # verpacken zip -r archiv.zip dir # Inhaltsverzeichnis des ZIP-Archivs archiv.zip ausgeben unzip -v archiv.zip # ZIP-Archiv archiv.zip entpacken unzip archiv.zip # der komplette Verzeichnisbaum, der bei dir beginnt, sowie die # auf .sh endenden Datei-/Verzeichnisnamen des aktuellen Verzeichnisses # werden in das gzip-komprimierte Tar-Archiv arch.tar.gz verpackt; # durch die Option v (verbose) wird jede ins Archiv aufgenommene Datei # protokolliert tar cfvz arch.tar.gz dir *.sh # dito, aber mit bzip2-Kompression statt gzip-Kompression tar cfvj arch.tar.bz2 dir *.sh # analoges unkomprimiertes Tar-Archiv erzeugen tar cfv arch.tar dir *.sh # Entpacken des bzip2-komprimierten Tar-Archivs arch.tar.bz2 # mit Protokollierung (Option v), Erhalt aller Zugriffsrechte # (Option p), existierende Dateien nicht überschreiben (Option k) tar xfvjkp arch.tar.bz2 # moderne tar-Implementierungen dekomprimieren komprimierte Archive # automatisch, so dass man die Option z oder j weglassen kann: tar xfvkp arch.tar.bz2 # dito für das gzip-komprimierte Tar-Archiv arch.tar.gz tar xfvzkp arch.tar.gz tar xfvkp arch.tar.gz # Archiv-Inhalt im kurzen Format ausgeben tar tf arch.tar tar tf arch.tar.gz tar tf arch.tar.bz2 # die Kompressions-Optionen z bzw. j kann man auch hier # bei modernen tar-Implementierungen weglassen # Archiv-Inhalt im langen Format (Option v) ausgeben tar tfv arch.tar tar tfv arch.tar.gz tar tfv arch.tar.bz2 # alle HTML-Dateien (Endung .html) ab dem aktuellen # Verzeichnis 1:1 ins Verzeichnis ~/backup (Verzeichnis backup # unterhalb des Home-Verzeichnisses des aktuellen Benutzers) kopieren tar cf - $(find . -name \*.html) | (cd ~/backup && tar xfvkp -) # Das Kommando find ermittelt die gesuchte Dateinamens-Liste. # Über die Kommando-Substitution wird diese Liste an das # Kommando tar übergeben. Da als Archiv-Name das Minus-Zeichen # verwendet wird, schreibt tar sein Archiv auf die Standard-Ausgabe. # Über eine Pipe übergeben wir dieses Archiv an eine Sub-Shell, die # zunächst ins Verzeichnis ~/backup wechselt und dann mittels # tar das aus der Pipe gelesene Archiv entpackt. Das Minus-Zeichen # als Archiv-Name symbolisiert hierbei die Standard-Eingabe. # Das cd der Sub-Shell hat keine Rückwirkung auf das erste # tar-Kommando in der Eltern-Shell. # extrahiere diejenigen Einträge aus einem Archiv, deren Endung mit # p beginnt (z.B. .py) archiv=~/backup/archiv.tgz tar xfvkp $archiv $(tar tf $archiv | grep '\.p[^.]*$') # Mit tar tf wird der Inhalt des Archivs ausgegeben. Mittels grep # suchen wir uns die Files/Einträge mit passendem Namen heraus. Die # von grep erzeugte Liste wird via Kommando-Substitution als die # Liste der zu extrahierenden Einträge an tar xfvkp übergeben.
Arbeit auf entfernten Rechnern:
# interaktives Secure-Shell-Login auf Rechner miller ssh miller # Kommando hostname via SSH auf dem entfernten Rechner miller # ausführen ssh miller hostname # Datei /etc/hosts ins Verzeichnis /tmp von Rechner miller kopieren scp /etc/hosts miller:/tmp
Drucken:
Allgemein stehen unter Linux typischerweise die Kommandos lp und lpr zum Ausdruck von Dateien zur Verfügung. Der konkrete Funktions-Umfang sowie die Optionen hängen davon ab, welches Druck-System (CUPS, LPRng) Verwendung findet. Die Details sind den Manuals zu entnehmem. Die folgenden einfachen Beispiele sollen die prinzipielle Handhabung zeigen:
# die Ausgabe von ls -l auf den Standard-Drucker ausgeben ls -l | lpr # die Ausgabe von ls -l auf den Drucker printer1 ausgeben ls -l | lpr -P printer1 # die Dateien file1 und file2 auf den Standard-Drucker ausgeben lpr file1 file2 # die Dateien file1 und file2 auf den Drucker printer1 ausgeben lpr -P printer1 file1 file2