bash - Die Bourne again shell

Inhaltsverzeichnis

  1. bash - Die Bourne again shell
    1. Vorwort
    2. Versionstand
    3. Start
    4. von bash benutzte Umgebungsvariablen
    5. Wie Befehle eingegeben werden können
    6. Steuercodes (Ctrl-)
    7. Eingebaute bash-Befehle
    8. Angabe von Dateinamen als Aufruf-Parameter
    9. Der Kommandozeileneditor
      1. wie vi
      2. wie emacs
    10. Links
    11. Beispiele für bash - scripts
    12. Tipps & Tricks
    13. Fragen und Antworten

Vorwort

bash ist die GNU/Linux-Standard-Shell. Sie wurde vom GNU-Projekt entwickelt. Sie ist abwärts kompatibel zur sh, der ursprünglichen Unix Shell. Shellskripte sollte man immer in sh bzw Bash schreiben und nicht in eine der zahlreichen anderen Shellvarianten (ksh, (t)csh).

Man kann damit nicht nur (wie unter DOS mit Batches) einfache Abläufe automatisieren, sondern richtige Programme erstellen, da diese Shell viel mächtiger ist und auch die UNIX-Befehle viel besser auf "Kooperation" nach dem Baukastensystem eingestellt sind.

Ab Version 2.04 bietet die bash eine programmierbare automatische Eingabe-Vervollständigung, siehe dazu den Bericht auf ProLinux: Die Tabulatortaste (TAB) ergänzt oft das angefangene Wort: Ist es eindeutig, reicht ein TAB, sonst listet ein zweites TAB die Alternativen auf. Ein Pieps zeigt an, dass keine Ergänzungsmöglichkeit gefunden wurde. Damit können Dateienamen, Kommandos, aber teilweise auch Parameter in Kommandos komfortabel und gedächtnisplatzschonend ergänzt werden.

Versionstand

Start

Der Kommandozeileninterpreter führt beim Start nacheinander die folgenden Dateien aus, in denen systemweite oder benutzer-spezielle Einstellungen vorgenommen werden können, die bei jedem Anmelden an das System vorgenommen werden:

  • ~/.bash_profile
  • ~/.bash_login
  • ~/.profile

Von bash wird aufgerufen: /etc/profile, dann ~/.bash_profile. Falls .bashrc aufgerufen wird, dann deswegen, weil ein Aufruf von ~/.bashrc im script ~/.bash_profile drinsteht.

In ~/.bashrc kann der Benutzer alle seine Abkürzungen und bevorzugten Einstellungen vornehmen.

Die Eingabeaufforderung kann angegeben werden durch die env-Variable PS1:

export PS1="\u \w #"

Besondere Bedeutung haben die Umschreibungen:

  • \h : Host name
  • \H : Host name inklusive Domain
  • \d : Datum
  • \t : time Zeit
  • \u : User Benutzerkennung
  • \w : Working directory, aktuelles Arbeitsverzeichnis
  • \l : Terminalname, zum Beispiel tty1
  • \# : Eingabezeilennummer
  • \\ : Das Zeichen "\"

Einen farbigen Prompt erreicht man durch die entsprechenden Escape-Codes. Beispiel:

export PS1="\[033円[1;73m\][\$(date +%H:%M)]\[033円[1;36m\][\[033円[1;34m\]\u\[033円[1;33m\]@\[033円[1;32m\]\h:\[033円[1;35m\]\w\[033円[1;36m\]]\[033円[1;31m\]\\$\[033円[0m\] "

Dies ergibt einen Prompt mit hellrotem Benutzernamen, grünem Hostnamen und orangem Arbeitsverzeichnis.

von bash benutzte Umgebungsvariablen

bash benutzt die folgenden env-Variablen

  • PATH=.:~/bin:/bin:/sbin:/usr/bin:/usr/sbin Suchpfad für externe Kommandos (Programme)
  • HOME Heimatverzeichnis aus /etc/passwd
  • MAILCHECK
  • TMOUT=n Nach n Sekunden die shell automatisch beenden
  • FIGORE=r:z Die Dateinamenerweiterungen bei Tab nicht beachten
  • PWD Das aktuelle Verzeichnis
  • OLDPWD Das letzte aktuelle Verzeichnis
  • $? Numerischer Wert der vom zuletzt aufgerufenen Kommando exit(2) zurückgegeben wurde.
  • 1ドル 2ドル Aufruf-Parameter
  • $# Anzahl der Aufruf-Parameter
  • $$ Prozessid der Shell. (Nützlich z.B. für eindeutige temporäre Dateinamen)

Hinweis: Wenn ein Script mit vorangestellten ". " (oder "source ") aufgerufen wird, dann wird keine neue Ausprägung von bash das Script ausführen, sondern die Eingabebash direkt. Nur so können Variablen von einem Script übernommen werden.

Wie Befehle eingegeben werden können

  • ls -R | grep tg | more

Durch den senkrechten Strich | wird die Ausgabe eines Programms (Prozess) in das nachfolgende Programm umgeleitet. 3 Programme werden dadurch gestartet : ls zeigt das Inhaltsverzeichnis an, grep sucht in der Ausgabe von ls nach dem Textstring "tg" und gibt nur die Zeilen weiter, die tg enthalten, more zeigt dann alles seitenweise an.

  • cd /tmp ; rm -f * ; ist ein "logischer Zeilenwechsel". Hier stehen also 2 Kommandos in einer Zeile.

  • ls -l >xxlst durch das Zeichen "Größer als" > wird die Ausgabe umgeleitet, hier im Beispiel in eine Datei.

  • ls >> xx2 Doppelter Pfeil: Anhängen an Datei

  • cp /x /y 2>error.log Nicht die Standardausgabe, sondern Kanal 2 (Fehlerausgabe) wird umgeleitet

  • for zuz in *.c ; do echo $zuz $zuz ; done Wiederhole mittleren Teil echo $zuz $zuz

  • find / -name "*.dat" >xx & ls -l > xxl & ist ebenfalls ein logischer Zeilenwechsel, startet den Prozess jedoch im Hintergrund, d.h. das Ende des Prozesses (hier find) wird nicht abgewartet sondern das nächste Kommando (hier ls) ausgeführt.

  • find / -name "*.dat" >xx & Starten im Hintergrund (kein 2. Kommando).

  • mount /dev/cdrom && cp /media/cdrom/* /backup : Das Copy-Kommando (cp) wird nur ausgeführt, wenn mount den Exit-Code 0 liefert ("kein Fehler")

  • cd /works || mkdir /works mkdir wird nur ausgeführt wenn cd nicht den Exit-Code 0 liefert ("Fehler")

  • ( liste ) Die Befehle "liste" werden in einer Sub-shell ausgeführt.

  • select ... : Kenne ich nicht, siehe man bash

Mit $ beginnen Variablennamen:

  • $$ : Prozessid
  • 1ドル .. 9ドル : Parameter der Kommandodatei
  • $# : Anzahl der Parameter
  • $NNNN : Einige besondere Namen , Siehe man bash
  • name=string text : Zuweisung von Environment-Variablen. Wenn die Variable aus der Datei .bashrc in die gestartete shell übernommen werden soll, dann muß auch export davorstehen.
  • <<WORT : HERE-Dokument: Alle Zeilen zwischen WORT und einer späteren Zeile mit WORT wird in die Eingabe (stdin) des Programmes geleitet. Siehe Beispiele.

Dateien werden von bash ausgeführt, wenn in der ersten Zeile steht:

Steuercodes (Ctrl-)

  • Control-c : Beenden des letzten Vordergrundprogramms.
  • Control-d : Beendet das Lesen von der Standardeingabe (End of File).
  • Control-v : Erlaubt die Eingabe von Control-Zeichen als Programmargumente. Bsp: qqmain VHVH

  • Control-z : Schickt des laufende Programm in den Hintergrund. Mit fg nummer kann es wieder in den Vordergrund geholt werden.
  • Control-a : Geht ans ende der aktuellen Zeile
  • Control-e : Geht an den Anfang der aktuellen Zeile

Eingebaute bash-Befehle

Hilfe über die eingebauten bash-Befehle gibt es mit help

  • alias name=text
  • bg
  • bind
  • break
  • builtin
  • case
  • cd

Standardverzeichnis wechseln. siehe #bsp_cd

  • command
  • continue
  • declare

declare -x PATH

  • Damit wird die gesetzte Env-Variable PATH in die aufrufende bash exportiert. Muß in den Einstellungsdateien angegeben werden.
  • dirs - Diese Kommando gibt den Namen des Arbeitsverzeichnisses zurück. pwd gibt den absoluten Pfad zurück, dirs gibt, wenn möglich den relativen Pfad zurück:

Eingabe:

cd
echo `pwd` `dirs`
cd /home/hjh/home/cc
echo `pwd` `dirs`
cd /tmp
echo `pwd` `dirs`

Anzeige:

hjh ~ : echo `pwd` `dirs`
/home/hjh ~
hjh ~ : cd /home/hjh/home/cc
hjh ~/home/cc : echo `pwd` `dirs`
/home/hjh/home/cc ~/home/cc
hjh ~/home/cc : cd /tmp
hjh /tmp : echo `pwd` `dirs`
/tmp /tmp
  • disown
  • echo Anzeigen / Ausgeben von Text

echo Kommando ist abgearbeitet

  • Zeigt den Text an.
  • enable
  • eval
  • exec
  • exit
  • export - macht aus einer Shellvariable eine Umgebungsvariable d.h. das sie mit in die Subshell(s) übernommen wird. Ein Beispiel:

lenny:~# VAR=wert
lenny:~# echo $VAR
wert
lenny:~# bash
lenny:~# echo $VAR

lenny:~# exit
lenny:~# echo $VAR
wert
lenny:~# export VAR=wert
lenny:~# echo $VAR
wert
lenny:~# bash
lenny:~# echo $VAR
wert
lenny:~#
  • false
  • fc
  • fg fg 1 holt den Prozeß 1, der durch Ctrl-Z in den Hintergrund, (engl. Background) geschickt wurde, wieder in den Vordergrund (engl. foreground).
  • for
  • for i in *.c; do base=basename $i .c ; rm $base.o ; done Löscht Object-Dateien, von denen Quellen existieren

  • function - Unterprogramme / Unter-Scripts im Shell-Script. Siehe #bsp_function
  • getopts
  • hash
  • help Hilfe zu den hier beschriebenen Kommandos
  • history Zeigt alle bisher eingegeben Befehlszeilen an.
  • if Startet ein Kette von Befehlen und fragt den letzten Rückgabewert ab.

Hinweis : Normalerweise stehen jedes der Wörter if then else fi in eigenen Zeile. Man kann aber auch den "logische Zeilenwechsel" ; verwenden.

  • jobs - Nach dem Starten eines Prozesses im Hintergrund ( prozessname & ) oder nach dem Stoppen eines Prozesses mit Strg+Z wird eine job-id vergeben. Das Kommando jobs zeigt die momentan vergebenen job-ids an.

  • kill sendet ein Signal an einen Prozess. Eine Liste der Signale gibt es mit kill -l. kill -9 PID bzw. kill -SIGKILL bricht einen Prozess ab, der nicht mehr auf Eingaben reagiert ("Zombie-Prozess). Standardmäßig ( kill PID ) wird das Signal SIGTERM (15) gesendet, was den Prozess auffordert, sich ordnungsgemäß zu beenden (exit 0).
  • let - mit let sind arithmetische Rechenoperationen möglich.
  • local local name=text setzt eine env-Variable
  • logout Beendet bash. Damit beendet ein Benutzer seine Anmeldung an seiner Konsole. Geht auch durch Dateiende ([Ctrl-d])
  • popd
  • pushd
  • pwd Print Working directory. Zeigt das aktuelle Arbeitsverzeichnis an.
  • read

read -p Welche_Datei_:

  • Läßt den Benutzer etwas eingeben. Das steht danach in der Variablen $REPLY

read -p Welche_Datei_: INPUT

  • Läßt den Benutzer etwas eingeben. Das steht danach in der Variablen $INPUT
  • readonly
  • return
  • set
  • shift
  • shopt
  • source
  • suspend
  • test Test gibt als Rückgabewert true (1) zurück, wenn wahr ist:
    • test -e dateiname ; Die Datei existiert test -r dateiname ; Die Datei existiert und ist lesbar test -w dateiname ; Die Datei existiert und ist schreibbar test -x dateiname ; Die Datei existiert und ist ausführbar test dateiname1 -nt dateiname2 ; Die Datei1 ist neuer als Datei2 test 1ドル = xx.cpp ; Die Zeichenketten links und rechts gleich sind.
  • time Zeigt an, wieviel Zeit ein Kommando verbraucht,
    • Beispiel: time lnk cpylines
  • times
  • trap
  • true ist immer wahr (gibt 1 zurück). Damit kann etwas immer wiederholt werden.
    • Beispiel : while true ; do echo zzz ; done ;
  • type Zeigt an, woher ein Befehl kommt.
    • hjh@hetol:~/home/cc/util$ type true true is a shell builtin hjh@hetol:~/home/cc/util$ type echo echo is a shell builtin hjh@hetol:~/home/cc/util$ type vim vim is /usr/bin/vim hjh@hetol:~/home/cc/util$
  • typeset
  • ulimit
  • umask - liefert die aktuell gesetzte umask (z. B. 0022)
  • unalias
  • unset - entfernt eine Variable komplett.
  • until
  • while : Beispiel, wie ein Kommando ( free ) alle 3 Sekunden wiederholt werden kann:

while true ; do clear ; free ; sleep 3s ; done ;

  • wait : wartet bis der Process mit der angegeben Nummer beendet ist.

Angabe von Dateinamen als Aufruf-Parameter

Programme werden bevorzugt aufgerufen mit Dateinamen. Die Programme selbst erhalten Argumente. Die shell, hier bash, erweitern Gruppen zu einer Liste einzelner Dateinamen. Nachfolgend der Aufruf eines Programms qqmain

  • qqmain abc.c : Wenn keine der Sonderzeichen enthalten sind wird der Parameter so übergeben, wie er eingegeben wurde.

  • qqmain *ser*.c : Alle Dateinamen (des aktuellen Arbeitsverzeichnisses) die "ser" enthalten und mit ".c" aufhören, werden übergeben.

  • qqmain qq[acf-m]*.cpp : in [] sind Buchstabengruppen enthalten, die einzeln aufgeführt sind wie 'a' und 'c' oder in einem Bereich von 'f' bis 'm' liegen.

  • qqmain [!q][!q]*.cpp ! ist die Negierung eines Bereichs.

Der Kommandozeileneditor

Ctrl-R l s Sucht rückwärts im Kommandozeilenspeicher (engl.: history) nach "ls"

Esc < Anfang des Kommandozeilenspeichers

Esc > Ende des Kommandozeilenspeichers

Den Kommandozeileneditor gibt es in zwei Ausführungen :

  • set -o vi : wie der Editor vi

  • set -o emacs : wie der Editor emacs

wie vi

wie emacs

  • Pfeiltasten bewegen die Einfügemarke (engl Cursor)

  • Esc-F positioniere Wortende

  • Esc-B positioniere Wortanfang

  • Ctrl-E positioniere Zeilenende

  • Ctrl-A positioniere Zeilenanfang

  • Ctrl-K Lösche bis Zeilenende

  • Ctrl-Y Einfügen aus Löschspeicher

  • Tab Dateinamen automatisch erweitern. Geht beim Befehl und auch bei den Argumenten.

Beispiele für bash - scripts

  • So wird der Suchpfad eines Benutzers erweitert :

In ~/.bashrc :

PATH=${PATH}:/home/hjh/home/cc/linux:/home/hjh/home/cc/bin
export PATH
  • Hinweis: viele shell - scripts sind in /bin oder in /usr/sbin.

Zum Anzeigen eingeben:

grep "#\!/bin/sh" *

Beispiel HERE-Dokument: Variablen werden expandiert:

cat >/tmp/killer <<EOS ; chmod +x /tmp/killer ; /tmp/killer
echo "Wir beenden die ausführende Shell!"
kill -9 $$
EOS

Ausgabe von grep kill /tmp/killer liefert:

kill -9 6893

Beispiel HERE-Dokument: Variablen werden nicht expandiert:

cat >/home/bin/my_profile <<"EOS" ; chmod +x /home/bin/my_profile
alias "my_pid=echo 'Aktuelle Prozess-Id: ' $$"
EOS

Ausgabe von grep alias /home/bin/my_profile liefert:

alias "my_pid=echo 'Aktuelle Prozess-Id: ' $$"

Tipps & Tricks

  • Eine kleine Einführung in die GnuTextUtilities: sed, tr, cut, ...

  • Mit script kann ich die Ein- und Ausgabe mitschneiden um sie mit später replay anzusehen (siehe BildschirmFoto).

  • Wie erstelle ich ein ShellScript und mache es ausführbar?

  • Wie kann ich (z.B. in einem Skript) einen TonAusgeben lassen?

  • Wie kriege ich einen ShellVariablenTeil zu fassen?

  • Wie kann ich selber Meldungen ins SysLog schreiben?

  • Shell-Scripts debuggen
    • Wenn man Shellscripts schreibt und diese nicht richtig funktionieren, ist die Fehlersuche meist sehr mühsam. Einfach am Anfang des Scripts folgenden Befehl einfügen, dann wird jede Zeile angezeigt bevor sie abgearbeitet wird: set -vx

  • Piepston erzeugen
    • Wenn man in einem Script einen Piepston ausgeben möchte, kann man dies mit folgender Anweisung erreichen: echo -e "\a"

  • M-., M-_ fügt das Argument des letzten Befehls ein.

  • Mit C-r kann man in der History rückwärts nach Befehlen suchen.

  • Mit !-1:gs/falsch/richtig ersetzt (s) man im letzten Befehl (!-1) falsch durch richtig, und macht dass für alle Vorkommen von falsch, also global (g).

  • Lösungen für "Argument list too long" finden sich hier.

  • Den aktuellen Pfad eines Scriptes bekommt man mit:
    • DIR=$(cd $(dirname 0ドル) 2>/dev/null && pwd)

Fragen und Antworten

Frage: ich muss ein Skript programmieren, das unter bash aber auch unter sh (Solaris) läuft. Wo bekomme ich ein sh für Linux ? -- ThomasKalka 2002年10月22日 14:52:14

  • welche sh? sh sagt eigentlich nur aus, das sie POSIX kompatibel ist. Abstufungen gibt es viele, ash, bash, csh, tcsh, zsh. -- BastianBlank 2002年10月22日 16:13:29

  • Die (t)csh ist nicht zur sh kompatibel
  • Unter den meisten Linuxdistributionen ist /bin/sh ein Link auf /bin/bash. Die Bash ist (aufwärts-)kompatibel zur sh. D.h die bash unterstützt alle Features der sh - aber nicht umgekehrt. Wenn Du Dein Skript einfach mit #!/bin/sh beginnst und nur die Standardfeatures verwendest, sollte das ganze auch auf der sh laufen. Zu den Standardfeatures würde ich mal die sh man page besuchen.

  • Danke. Würde gerne aber unter Linux testen und nicht unter Solaris. Wäre schön, wenn jemand etwas kennt. Sollen wir eine Seite GesuchteSoftware einrichten ? --ThomasKalka

  • wenn du POSIXLY_CORRECT setzt, müsste es eigentlich passen -- RonnyBuchmann 2002年11月18日 16:13:57

  • Das Debian-Paket ash enthält die /bin/sh aus NetBSD. Das ist tatsächlich eine sh und keine bash. -- BennySiegert 2002年11月18日 17:31:14

  • Ansonsten gibt es natürlich auch die bash für Solaris, dürfte im Endeffekt einfacher sein wenn Du das installieren darfst (Die "plain" Shell kann nicht sonderlich viel). Findest Du bspw. unter http://www.sunfreeware.com

  • Die "ash" (oder auch "dash") ist POSIX kompatibel und hat fast keine Erweiterungen. Wenn etwas also mit ash läuft, sollten die meisten Bourne Shells damit zurecht kommen. Außerdem lädt die "ash" wesentlich schneller, als die "bash". -- AndreasFoerster 2006年07月01日 14:51:11

Frage: wie verhindere ich unkorrekte Umbrüche bei farbigen Prompts?

  • Das vorzeitige Umbrechen und das falsche Zeilenspringen wenn bei Umbruch am Zeilenanfang Zeichen mit Backspace gelöscht werden liegt daran das die Bash die ANSI-Sequenzen im Prompt als sichtbare Zeichen mitzählt. Damit glaubt die Bash weniger Zeichen vom Zeilenende entfernt zu sein als sie wirklich ist und bricht vorzeitig um. Lösung ist das Klammern aller nicht mitzuzählender Zeichen im Prompt (also der ANSI-Sequenzen für die Farben) mit "\[" vor und "\]" hinter dem nicht mitzuzählendem Teilstring.
  • Bash/History

Bash (zuletzt geändert am 2010年10月21日 15:18:13 durch MarcusSchiemann )

AltStyle によって変換されたページ (->オリジナル) /