Shell

Die Kommandozeile (bzw. die Shell oder das Terminal)

Wenn hier die Rede von Shell ist ist immer die bash-Shell (Standard-Kommandozeileninterpreter unter Linux und Mac OS X) gemeint. Interessante Alternativen zur bash sind die Z-Shell (zsh) (bietet unter anderm TAB-Completion nicht nur für Befehle sondern auch für Befehlsoptionen, siehe auch Guckes,Plenz: Zsh. Die magische Shell) und die Windows Power Shell die einen objektorientierten Ansatz verfolgt.

Wer auf der Suche nach den beliebtesten Bash-Tricks ist, dem sei www.commandlinefu.com und what-is-your-single-most-favorite-command-line-trick-using-bash empfohlen. Wer erstmal nur einen guten und schnellen Überblick über den bash-Kommandozeileninterpreter sucht wird bei c’t 1299 fündig. Dieser Artikel sei jedem als Ergänzung zu den folgenden Tipps empfohlen.

  • Einen symbolischen Link anlegen:
    > ln -s [ZielName] [LinkName] 
    
    wobei [Zielname] das bereits existierende Verzeichnis/Datei ist und [LinkName] der symbolische Name/Pfad der dafür angelegt werden soll. Solche symbolischen Links sind äußerst nützlich. Hat z.B. wieder irgendein fauler Programmier absolute Pfade im (Installations-)Programm hardcodiert, kann man mit Hilfe von symbolischen Links diese Pfade auf die gewünschten "umbiegen".
  • Ins vorherige Verzeichnis zurückspringen:
    > cd -
    
    Dieser Befehl erlaubt es in das vorherige Verzeichnis zurückzuspringen, ohne vorher zehnmal cd .. oder ähnliches aufzurufen. Er entspricht dem Kommando
    > cd "$OLDPWD" && pwd
    
    der also in das vorherige Verzeichnis springt und nach dem Sprung den Namen diese Verzeichnisses ausgibt (siehe auch www.opengroup.org).
  • Einen Prozess im Hintergrund starten, so dass er auch beim Schließen der Kommandozeile weiterläuft:
    > ./command &
    Achtung: Beim Schliessen der Kommandozeile per Fenster-Icon wird command trotzdem beendet! Nur wenn das Terminal per
    > exit
    beendet wird läuft command weiter.
  • Einen Prozess nachträglich in den Hintergrund stellen:
    Hat man das & vergessen um einen Prozess im Hintergrund zu starten, kann man den Prozess mit ctrl-z pausieren und dann durch Eingabe von bg in den Hintergrund schicken, z.B.
    > ./skype
    [ctrl]-[z]
    [1]+  Stopped ./skype
    > bg
    [1]+ ./skype &
    
    Siehe dazu auch netcosmos.de und www.hcidata.info/background-job.htm
  • Einen Prozess so starten, dass er auch nach einem Logout weiterläuft:
    > nohup command &
    Dies funktioniert auch mit parallelisierten Programmen, z.B. für ein mit MPI parallelisiertes Programm, welches in vier parallelen Prozessen laufen soll :
    > nohup mpirun -np 4 mpicommand 2>&1 > output.log & 
    Aber Achtung: Wenn der Prozess z.B. mit | Ausgaben umleitet, oder mit tee Ausgaben in die Kommandozeile schreibt, funktioniert das anscheinend nicht; z.B. würde folgender Prozess beim Schließen des Terminals abgebrochen:
    > nohup command 2>&1 | tee output.log & 
    Siehe auch Pircher 2003.
  • Umleiten der Ausgabe von STDERR(2) und STDOUT(1) in eine Datei:
    > ./command 1>command.log 2>&1 
    ACHTUNG: Die Reihenfolge der Umleitungen ist signifikant. Würde man 2>&1 vor 1>command.log schreiben, so leitet man nur STDOUT in die Datei command.log um; STDERR wird jedoch nur auf den Kanal umgeleitet der vorher STDOUT war (meist das Terminal), d.h. man sieht die Fehlermeldungen im Termial und alle anderen Ausgaben werden in die Datei umgeleitet (Siehe dazu auch die Unix-Anleitung der Uni Erlangen).
    Will man die Ausgabe gleichzeitig noch in der Shell sehen, so kann muß man die Weiterleitung der Ausgabe mit dem Pipezeichen | mit dem T-Stück "tee" verzweigen:
    > ./command 2>&1 | tee command.log
  • Ausgehend vom aktuellen Verzeichnis alle Dateien mit der Endung "suffix" finden:
    > find . -name "*.suffix"
    Wichtig sind dabei die Anführungszeichen. Ohne sie kommt es zu seltsamen Fehlern, wenn das gesuchte Suchmuster das Jokerzeichen * enthält. Möchte man dabei die Ausgabe von Fehlermeldungen wie find: permission denied vermeiden, so kann man diese nach /dev/null umleiten:
    > find . -name "*.suffix" 2>/dev/null
  • Ausgehend vom aktuellen Verzeichnis alle Dateien, die in den letzten 30 Tagen modifiziert wurden, finden:
    > find . -mtime -30 -ls
    Wichtig ist dabei das Minuszeichen vor der 30. Vergisst man es werden nur die Dateien angezeigt, die genau vor 30 Tagen geändert wurden. Gibt man stattdessen +30 an, werden die Dateien gesucht, welche vor mehr als 30 Tagen geändert wurden. Die Option -ls sorgt dafür, dass find die Dateien im selben Format anzeigt wir der Befehl ls -dils. Damit sieht man gleich das Änderungsdatum der gefundenen Dateien.
  • Ausgehend vom aktuellen Verzeichnis rekursiv in allen Unterverzeichnissen bestimmte Dateien/Verzeichnisse loeschen:
    Will man z.B. alle .svn-Verzeichnisse rekursiv löschen nutzt man find um die Parameterliste fuer rm zu erzeugen:
    > rm -rf `find -name ".svn"`
    Der obige Befehl funktioniert, da die Shell ein Kommando zwischen zwei Backticks (`) durch die Ausgabe dieses Kommandos ersetzt (siehe auch c't 12/99). Aufpassen muß man jedoch: Auch Dateien namens .svn werden durch obiges Kommando geloescht!
  • Suchen eines Begriffes in allen Dateien des aktuellen Verzeichnisses und der Unterverzeichnisse:
    Lösung 1 (unter Suse Linux):
    > grep -r "Suchbegriff"
    
    Lösung 2: Die Option -r für grep ist nicht in allen Linux/*NIX-Distributionen vorhanden. Dann kann man folgendes verwenden:
    > find -exec grep "Suchbegriff" {} \; -print
    Gefunden in Kofler 2004. Achtung: wenn der Suchbegriff mit Sonderzeichen durchsetzt, muß man diese mit einem oder mehreren(!) "Backslashes escapen". Sucht man z.B. "rm -f $*.f" so muß man als Suchbegriff "rm -f \\$\*.f" eingeben (Man beachte den doppelten(!) Backslash vor dem $-Zeichen).
  • Nach Größen sortierte Ausgabe aller Dateien und Verzeichnisse im aktuellen Verzeichnis:
    > du --max-depth=1 -all -k | sort -n
    Dabei steht --max-depth=1 dafür, dass nur die Unterverzeichnisse im aktuellen Verzeichnis aufgelistet werden und nicht auch noch die Unterverzeichnisse in den Unterverzeichnissen. Die Option -all steht dafür, dass auch die Größen der Dateien im aktuellen Verzeichnis angezeigt werden und die Option -n des sort-Befehls sortiert die übergebene Liste numerisch. Die Option -k gibt an, dass die Größenangabe in Kibibyte (=1024 Byte) sein soll und ist eine Abkürzung für -B 1K Die Option -B 1KB steht für Kilobyte (=1000Byte) und entsprechend steht -B 1M für Mebibyte (=1024*1024=1048576 Byte) und -B 1MB für Megabyte (=1000000 Byte) usw. für G, T, P, E, Z, Y. Zudem wird immer auf die nächstgrößere Zahl gerundet, d.h 4096 Byte entsprechen 4 Kibibyte aber aufgerundet sind das 5 Kilobyte. Wen das alles verwirrt, der kann auch -B 1 setzen und bekommt die Größen in Byte angezeigt oder mehr zum Thema Kibibyte und Mebibyte lesen und zwar beim NIST (National Institut of Standards and Technology) oder in der Wikipedia.
  • Zwei unterschiedlich sortierte Dateien vergleichen:
    Um zwei Dateien (file1, file2) bequem zu vergleichen, die ähnliche Inhalt haben, aber vielleicht auf unterschiedliche Weise sortiert sind, hilft folgender Befehl:
    > diff -rcs <(sort file1) <(sort file2) | kompare -o -
    
    Zuerst werden die zwei Dateien sortiert und an diff übergeben. Der Parameter -rcs sorgt dafür, dass das Ausgabeformat von diff vom graphischen Diff-Tool Kompare verstanden werden kann. Mit | kompare -o - wird die Ausgabe von diff an kompare weitergeleitet und kompare gestartet.
  • Befehlsabkürzungen (Aliase) und Funktionen:
    Für häufig benötigte lange Befehlszeilen schreibt man am besten Abkürzungen, sog. Aliase. Diese werden in der Datei .alias im Homeverzeichnis angelegt. Meine .alias-Datei enthält z.B. folgende Zeile:
    alias platz="du --max-depth=1 -all -k | sort -n"
    Durch Eingabe von platz kann ich mir damit also immer die Größe aller Dateien und Verzeichnisse (s. oben) anzeigen lassen. Durch Eingabe von alias kann man sich alle (auch global) gesetzten Befehlsabkürzungen anzeigen lassen. Alias-Anweisungen mit Übergabe eines Arguments sind in der Bash-Shell jedoch nicht möglich, dafür gibt es Funktionen, welche man in der Datei .bashrc definieren kann. Um z.B. eine Funktion der Art such begriff zu definieren, die alle Dateien (auch die, die ev. in Unterverzeichnissen vom aktuellen Verzeichnis aus gesehen liegen) anzeigt, welche "begriff" enthalten, muss man folgende Zeile in die .bashrc einfügen:
    such() { find -exec grep $1 {} \; -print; }
    Wichtig dabei ist, dass man nach der ersten geschweiften Klammer, bzw. vor der letzten geschweifen Klammer immer ein Leerzeichen lassen muß, ansonsten funktioniert es nicht. $1 steht übrigens für das erste übergebene Argument nach dem Kommando selbst (s. auch Shellskript-Programmierung weiter unten). Ausführen kann man das Suchkommando jetzt mit
    such test
    Das Ergebnis sind ist eine Liste aller Dateien auch in den Unterverzeichnissen, welche "test" enthalten. Zusätzlich wird auch die Zeile in der der Begriff vorkommt angezeigt.
  • Kommandos zu einem bestimmten Zeitpunkt ausführen lassen:
    Mithilfe der at-Kommandos kann man Befehle zu einem vorbestimmten Zeitpunkt ausführen lassen. Dazu ist es nötig, dass der atd-Dienst läuft (s. Linux/Administration). Läuft dieser Dienst, kann man, wenn man z.B. einen Befehl einen Befehl an einem bestimmten Datum zu einer bestimmten Zeit ausführen möchte, folgendes eingeben:
    > at 05:00 30.08.05
    Dies würde alle folgenden Befehle um fünf Uhr morgens am 30. August 2005 starten (Mehr zur Datums- bzw. Zeitsyntax siehe man at). Um einen Befehl in fünf Minuten auszuführen kann man aber auch folgendes eingeben:
    > at now +5 minutes
    Nach Eingabe des at-Kommandos erscheint dann immer folgende Eingabezeile:
    at>
    Hier kann man nun interaktiv einen, bzw. mehrere Befehle hintereinander eingeben, welche dann in dieser Reihenfolge zum gegebenen Zeitpunkt gestartet werden. Abschliessend muß man die Tastenkombination Ctrl-d (Nicht Ctrl-c, das beendet at ohne das es sich die eingegebenen Befehle merkt) drücken. Die Ausgabe des Befehls wird dann nach Ausführung als Email an username@computername.domainname geschickt (Dies kann man auch ändern, wenn gewünscht). Mit Hilfe von atq kann man alle anstehenden Jobs (als Superuser sogar alle anstehenden Jobs aller Benutzer) ansehen:
    > atq
        5   2005-08-30  05:00   a   asmaier
    Dabei steht die erste Zahl für die Jobnummer, darauf folgt das Datum und die Uhrzeit zu der der Job ausgeführt werden soll, dann folgt die Angabe der Warteschlange (Queue) in der der Befehl steht (Man kann nämlich mehrere Queues erzeugen, a ist allerdings die Default-Queue) und abschließend der Name des Benutzers der den Job in Auftrag gegeben hat. Will man einen Job wieder löschen kann man dies folgendermaßen tun:
    atrm 5
    Dabei steht die angegebene Nummer für die unter atq angezeigte Jobnummer, welche man löschen will. Mehr zur Benutzung von at findet man unter anderem in der Linuxfibel.
  • Alle laufenden Prozesse anzeigen (BSD Syntax, siehe auch man ps):
    > ps aux
    Die Option a zeigt alle Prozesse auch der anderen Benutzer (und nicht nur die Eigenen) an, die Option x zeigt zusätzlich alle Prozesse an denen kein Terminal zugeordnet ist (z.B. Dienste bzw. Daemons oder X-Server-Prozesse) und die Option u zeigt zusätzliche Informationsspalten wie die Benutzerkennung unter der der Prozeß läuft, aktueller Speicher- und Rechenzeitverbrauch, Startzeit des Prozesses und weitere an. Zusätzlich kann man noch die Option w setzen; dann wird die Anzeige breiter. Setzt man w zweimal, so wird wirklich alles angezeigt und auch lange Kommandozeilen für Prozessaufrufe nicht abgeschnitten.
  • Anzeige der CPU-intensivsten Prozesse:
    > top

    Tastaturkürzel für top:

    • Prozess beenden: k
    • Prozesse eines bestimmten Benutzers anzeigen: u
    • Belastung der einzelnen CPUs getrennt anzeigen: 1
  • Anzeige aller Umgebungsvariablen unter Linux:
    > env
  • Anzeige aller Dateien auf die ein Programm beim Start zugreift:
    > strace [Programmname]
  • Anzeige aller Benutzergruppen zu denen man gehört:
    > groups
  • Anzeige von Hard- und Softwareinformationen:
    Um welche Linuxversion es sich handelt erfährt man standardgemäß mittels
    > lsb_release -a
    Sollte dieser Befehl nicht funktionieren so erfährt man die Versionsnummer von SuSE in der Datei /etc/SuSE-release, von Debian in /etc/debian-version und von Solaris in /etc/release (siehe auch die ausführliche Liste unter www.kubieziel.de). Informationen über den Prozessor und die Speicherausstattung findet man in Linux mit
    > less /proc/cpuinfo
    > less /proc/meminfo
    
    Unter Solaris 10 hilft der Aufruf von
    > prtdiag
    weiter (siehe auch www.lifeaftercoffee.com). Die MAC-Adresse bekommt man ohne(!) root-Rechte heraus indem man die Datei /var/log/boot.msg betrachtet. Dort sucht man nach den Zeilen
    ...
    Setting up network interfaces
    ...
    eth0 configuration: eth-id-[MAC-Adresse]
    eth0 IP address: [IP-Adresse]
    ...
    
    wobei [MAC-Adresse] die gesuchte MAC-Adresse darstellt und [IP-Adresse] die IP-Adresse des Rechners ist. Klappt dieser Trick jedoch nicht, steht unter Administration wie man die MAC-Adresse als Root findet.
    Eine Liste aller zu mountenden Laufwerke findet man in der /etc/fstab-Datei, die Liste aller tatsächlich gemounteten Laufwerke steht in /etc/mtab, wobei letztere Datei automatisch erzeugt wird und daher nicht per Hand editiert werden sollte.
  • Anzeige von Informationen wie (Alias-)Namen und IP Adressen von Internetresourcen:
    > host www.google.de
    www.google.de is an alias for www.google.com.
    www.google.com is an alias for www.l.google.com.
    www.l.google.com has address 74.125.43.147
    www.l.google.com has address 74.125.43.99
    www.l.google.com has address 74.125.43.103
    www.l.google.com has address 74.125.43.104
    www.l.google.com has IPv6 address 2001:4860:a003::68
    
    Auch "reverse-lookup", d.h. die Ausgabe des Namens zu einer bestimmten Internetadresse ist möglich
    > host 74.125.43.147
    147.43.125.74.in-addr.arpa domain name pointer bw-in-f147.google.com.
    
    Wie die Ausgabe zu interpretieren ist wird ausführlich bei www.rickconner.net beschrieben. Eine veraltete (aber unter Windows die einzig mögliche) Alternative zu host ist nslookup, welches jedoch nicht mehr benutzt werden sollte (siehe nslookup-flaws). Stattdessen sollte man, wenn man noch mehr Informationen habe möchte als host anbietet, das Kommando dig verwenden:
    > dig www.google.de
    
    ; <<>> DiG 9.3.4 <<>> www.google.de
    ;; global options:  printcmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42579
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 7, ADDITIONAL: 7
    
    ;; QUESTION SECTION:
    ;www.google.de.                 IN      A
    
    ;; ANSWER SECTION:
    www.google.de.          72639   IN      CNAME   www.google.com.
    ...
    
    ;; AUTHORITY SECTION:
    l.google.com.           72822   IN      NS      f.l.google.com.
    ...
    
    ;; ADDITIONAL SECTION:
    a.l.google.com.         160307  IN      A       209.85.139.9
    ...
    
    ;; Query time: 0 msec
    ;; SERVER: 10.156.33.53#53(10.156.33.53)
    ;; WHEN: Mon May 11 18:17:32 2009
    ;; MSG SIZE  rcvd: 367
    
    Einen guten Überblick über host, dig und nslookup findet man auch bei www.tuaw.com. Weitere nützliche Tools zur Netzwerkanalyse werden bei www.linux-user.de beschrieben.
  • Anzeige aller eingeloggten Benutzer auf einem Computer:
    > finger
    ...
    max64mu    Max Muster           *pts/20      -     Mon 17:20
    root       root                  pts/0    8:12  Nov  2 2008  jmb01.de
    root       root                 *pts/2    8:12     Wed 10:48 jmb01.de
    
    Der finger-Befehl gibt dabei die meisten Informationen zurueck, z.B. zeigt er im obigen Beispiel zwei Verbindungen des root-Benutzers an, die bei Benutzung des who-Kommandos
    > who
    ...
    max64mu  pts/20       2009-05-11 17:20
    
    nicht aufgelistet werden. Allerdings wird der finger-Dienst genau wegen seiner Geschwätzigkeit und der Möglichkeit ihn auch aus aus der Entfernung abzufragen oft als Sicherheitsrisiko gesehen und ist daher oft abgeschaltet. Dann bleibt nur die Benutzung von who, bzw. w, welches z.B, auch den zuletzt ausgeführten Befehl eines jeden Benutzers anzeigt
    > w
    USER     TTY        LOGIN@   IDLE   JCPU   PCPU WHAT
    ...
    max64mu  pts/20    17:20    0.00s  0.02s  0.00s w
    
  • Laufende Veränderungen in einer (Log-)Datei betrachten:
    > less +F logdatei
    Dieses Kommando startet less im sogenannten Tail-Modus, wobei less automatisch Veränderungen am Ende der Datei anzeigt. Um vom Tail-Modus in den normalen Modus zu wechseln einfach Ctrl-c drücken (siehe linuxcommando.blogspot.com). Will man jedoch mehr als eine Datei beobachten reicht less nicht aus, dann muß man tail verwenden (siehe linuxcommando.blogspot.com):
    > tail -f logdatei1 logdatei2
  • Änderungen an der .bashrc-Konfigurationsdatei ohne Neustart der Shell wirksam werden lassen:
    > source ~/.bashrc
    Alternativ (aber vielleicht etwas verwirrend kann man auch)
    > . ~/.bashrc
    verwenden. Dies funktioniert sehr allgemein also z.B auch mit den Befehlen der .alias-Datei
    > source ~/.alias
    Mehr zur Funktionsweise des source-Kommandos steht unter learnlinux.tsf.org.za.
  • Zeilenumbruch in less abschalten:
    Entweder die Datei über die Kommandozeile mit
    > less -S 
    aufrufen, oder bei der Anzeige der Datei -S drücken. Mit der Cursortaste kann man dann nach links und rechts navigieren.
  • Anzeigen einer Liste aller zuletzt eingegebenen Befehle:
    > history
    Leider ist diese Liste dann nicht komplett, wenn man mehrere Shell-Fenster gleichzeitig geöffnet hat, denn standardmäßig werden immer nur die Befehle der zuletzt geschlossenen Shell fuer die Zukunft gespeichert. Befehle aus vorher geschlossenen Shells gehen verloren. Abhilfe bringt nach www.mynethome.de das Hinzufügen der Zeilen
    shopt -s histappend
    PROMPT_COMMAND='history -a'
    
    zur .bashrc. Mehr zu dieser Lösung und anderen fortgeschrittenen bash-Themen findet man in Myers: Power Shell Usage (2003).
  • Cursorsteuerung:
    Um bei langen Befehlszeilen den Cursor an den Anfang springen zu lassen drücke man Ctrl-a, um wieder ans Ende zu gelangen Ctrl-e.
Avatar
Andreas Maier
Data Alchemist

My interests include machine learning, software development, physics and mathematics

Related