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 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:
Die Seite Drucken unter UNIX/Linux gibt Hinweise zum Drucken mit Kommandozeilen- und grafischen Werkzeugen, wobei das dort erwähnte Kommando print in seiner konkreten Ausprägung eine Spezifik der TU Chemnitz ist.
Allgemein stehen unter Linux statt print 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 Verwendung findet. Vielfach wird primär auf CUPS orientiert, allerdings ist teilweise auch noch LPRng im Einsatz. Beide Systeme können koexistieren.
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