Die Shell-Umgebung ist mehr als die Summe ihrer Variablen. Sie umfasst alles, was deine Sitzung definiert: Variablen, Aliases, Funktionen, History, das aktuelle Verzeichnis und die offenen Datei-Deskriptoren. Wer versteht, wann welche Init-Datei gelesen wird und wo persistente Konfiguration hingehört, vermeidet die häufigste Frustration auf der Kommandozeile — dass Änderungen nach dem nächsten Login wieder weg sind.
Was ist die Shell-Umgebung?
Wenn du ein Terminal öffnest, startet ein Shell-Prozess. Dieser Prozess hat einen eigenen Kontext, der zusammen die Shell-Umgebung bildet. Sie besteht aus mehreren Komponenten, die du dir wie ein Inventar der laufenden Sitzung vorstellen kannst.
| Komponente | Beschreibung |
|---|---|
| Variablen | Lokale Shell-Variablen und exportierte Umgebungsvariablen wie HOME, PATH, USER |
| Aliases | Kurzformen für längere Befehle, etwa ll für ls -la |
| Funktionen | Selbstdefinierte Shell-Funktionen mit Logik und Argumenten |
| History | Liste der zuletzt eingegebenen Befehle, meist in ~/.bash_history |
| Working Directory | Das aktuelle Verzeichnis, abrufbar mit pwd |
| Datei-Deskriptoren | Offene Verbindungen zu stdin, stdout, stderr und weiteren Streams |
Wer erzeugt diese Umgebung? Beim Start liest die Shell eine Reihe von Init-Files — Konfigurationsdateien wie .bashrc oder .bash_profile — und führt sie der Reihe nach aus. Diese Skripte setzen Variablen, definieren Aliases und laden Funktionen. Welche Datei gelesen wird, hängt davon ab, wie die Shell gestartet wurde.
Login-, Interactive- und Non-Interactive-Shell
Die Bash unterscheidet zwei orthogonale Eigenschaften: Login vs. Non-Login und Interactive vs. Non-Interactive. Daraus ergeben sich vier Kombinationen, die jeweils unterschiedliche Init-Files lesen.
| Variante | Wann tritt sie auf? | Gelesene Init-Files (Bash) |
|---|---|---|
| Login + Interactive | tty-Login, SSH-Verbindung, bash -l, macOS-Terminal-Tab (historisch) | /etc/profile, dann erste vorhandene aus ~/.bash_profile, ~/.bash_login, ~/.profile |
| Non-Login + Interactive | Neues Terminal-Tab unter Linux, bash in laufender Sitzung | /etc/bash.bashrc, ~/.bashrc |
| Login + Non-Interactive | Selten, etwa ssh host -- befehl mit erzwungenem Login | wie Login + Interactive, aber ohne Prompt |
| Non-Login + Non-Interactive | Shell-Skripte mit #!/bin/bash, Cron-Jobs | Nur BASH_ENV, falls gesetzt — keine Init-Files |
Die wichtigste Konsequenz: Cron-Jobs und Skripte sehen deine Aliases nicht. Aliases werden nur in interaktiven Shells eingelesen. Ähnlich frustrierend ist, dass eine SSH-Sitzung manchmal andere Variablen sieht als ein lokales Terminal — denn SSH öffnet eine Login-Shell, ein typisches Linux-Terminal aber eine Non-Login-Interactive-Shell.
So findest du heraus, in welcher Variante du gerade steckst:
shopt -q login_shell && echo "Login-Shell" || echo "Non-Login-Shell"
[[ $- == *i* ]] && echo "Interactive" || echo "Non-Interactive"Init-Files: bashrc, bash_profile, profile
Die Init-Files liegen in deinem Home-Verzeichnis und im Systemverzeichnis /etc. Sie werden von der Shell beim Start ausgeführt und konfigurieren so deine Umgebung.
| Datei | Wann gelesen | Typischer Inhalt |
|---|---|---|
/etc/profile | Login-Shell, systemweit | PATH, umask, systemweite Variablen |
/etc/profile.d/*.sh | Über /etc/profile eingebunden | Modulare Pakete, etwa bash_completion |
~/.bash_profile | Login-Shell, benutzerspezifisch | Login-spezifische Variablen, oft nur Wrapper für .bashrc |
~/.bash_login | Login-Shell, falls .bash_profile fehlt | Selten verwendet, gleicher Zweck wie .bash_profile |
~/.profile | Login-Shell, falls keine der beiden oben existiert | POSIX-kompatibler Fallback, auch von dash und sh gelesen |
/etc/bash.bashrc | Interactive Non-Login, systemweit (Debian/Ubuntu) | Systemweite Aliases, Prompt-Defaults |
~/.bashrc | Interactive Non-Login, benutzerspezifisch | Aliases, Funktionen, Prompt, Shell-Optionen |
~/.bash_logout | Beim Verlassen einer Login-Shell | Aufräumarbeiten, Cache leeren |
Die übliche Empfehlung lautet: Alles Interaktive in ~/.bashrc, und ~/.bash_profile als Wrapper, der ~/.bashrc einbindet. Damit funktioniert deine Konfiguration sowohl beim lokalen Terminal als auch nach SSH-Login identisch.
# Login-spezifische Variablen
export PATH="$HOME/.local/bin:$PATH"
# Interaktive Konfiguration einbinden
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fiZsh hat eine ähnliche, aber nicht identische Aufteilung: ~/.zshenv (immer), ~/.zprofile (Login), ~/.zshrc (Interactive), ~/.zlogin (Login, nach .zshrc). Auf macOS ist Zsh seit Catalina die Standard-Shell.
Variablen anzeigen und setzen
Die Shell unterscheidet zwischen Shell-Variablen (nur in der aktuellen Shell sichtbar) und Umgebungsvariablen (an Kind-Prozesse vererbt). Die wichtigsten Befehle dafür kennst du vielleicht schon — hier der Überblick im Kontext der Umgebung.
| Befehl | Zweck |
|---|---|
env | Zeigt alle exportierten Umgebungsvariablen |
printenv | Wie env, aber kann auch eine einzelne Variable abfragen: printenv HOME |
set | Zeigt alle Shell-Variablen, Funktionen und Optionen — deutlich mehr als env |
export VAR=wert | Setzt eine Umgebungsvariable, sichtbar für Kind-Prozesse |
VAR=wert | Setzt nur eine lokale Shell-Variable |
unset VAR | Entfernt eine Variable komplett |
declare -p VAR | Zeigt Typ und Wert einer Variable im Detail |
Ein praktischer Test der Differenz:
lokal="nur hier"
export global="auch im Kind"
bash -c 'echo "lokal=$lokal global=$global"'lokal= global=auch im KindDetails zur Variablen-Syntax, Sonderzeichen wie $?, $# und Quoting findest du im Artikel Variablen.
Wichtige Standard-Umgebungsvariablen
Diese Variablen sind auf praktisch jedem Unix-System gesetzt. Programme verlassen sich darauf — ein falsch gesetztes LANG oder TERM führt schnell zu kaputtem Output.
| Variable | Bedeutung | Wo gesetzt |
|---|---|---|
HOME | Pfad zum Home-Verzeichnis des Users | Login-Prozess |
USER, LOGNAME | Aktueller Benutzername | Login-Prozess |
SHELL | Pfad zur Login-Shell (aus /etc/passwd) | Login-Prozess |
PATH | Suchpfade für ausführbare Programme | /etc/profile, ~/.profile |
PWD | Aktuelles Arbeitsverzeichnis | Shell, automatisch |
OLDPWD | Vorheriges Verzeichnis, Ziel von cd - | Shell, automatisch |
EDITOR | Standard-Editor für Tools wie git commit oder crontab -e | ~/.bashrc oder ~/.profile |
VISUAL | Wie EDITOR, aber für vollwertige Editoren statt Zeileneditoren | ~/.bashrc |
PAGER | Standard-Pager, meist less | ~/.bashrc |
LANG | Sprach- und Locale-Einstellung, etwa de_DE.UTF-8 | /etc/locale.conf, /etc/default/locale |
LC_* | Feinkontrolle einzelner Locale-Aspekte (Zeit, Zahlen, Sortierung) | wie LANG |
TERM | Terminal-Typ, etwa xterm-256color | Terminal-Emulator beim Start |
TZ | Zeitzone, etwa Europe/Berlin | optional, sonst System-Default |
TMPDIR | Verzeichnis für temporäre Dateien | optional, meist /tmp |
MANPATH | Suchpfade für Manpages | man selbst, oder ~/.bashrc |
XDG_CONFIG_HOME | Basis für User-Config, Default ~/.config | XDG-konforme Anwendungen |
XDG_DATA_HOME | Basis für User-Daten, Default ~/.local/share | XDG-konforme Anwendungen |
Wenn du eine dieser Variablen dauerhaft setzen willst, gehört der export-Befehl in ~/.bashrc (für Interactive) oder ~/.profile (auch für GUI-Anwendungen, die kein Terminal öffnen).
Aliases
Ein Alias ist eine Kurzform für einen längeren Befehl. Aliases gelten nur in interaktiven Shells und werden nicht an Kind-Prozesse vererbt.
alias ll='ls -la'
alias gs='git status'
alias ..='cd ..'
# Alle Aliases anzeigen
alias
# Einen Alias entfernen
unalias llDamit Aliases dauerhaft verfügbar sind, gehören sie in ~/.bashrc. Manche Distributionen lagern sie in eine eigene Datei ~/.bash_aliases aus, die dann von ~/.bashrc eingebunden wird:
# In ~/.bashrc:
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fiWenn du einen Alias temporär umgehen willst — etwa weil ls als ls --color=auto aliasiert ist und du das Original brauchst — stell dem Befehl einen Backslash voran:
\ls /etcAlternativ funktionieren auch command ls oder /bin/ls.
Funktionen statt Aliases
Aliases sind eine reine Textersetzung am Zeilenanfang. Sobald du Argumente verarbeiten oder Logik einbauen willst, brauchst du eine Shell-Funktion. Funktionen sind sichtbar wie Aliases nur in der aktuellen Shell, lassen sich aber wie ein Befehl mit Argumenten aufrufen.
mkcd() {
mkdir -p "$1" && cd "$1"
}$1 ist das erste Argument. Mit mkcd projekt-x legst du jetzt das Verzeichnis an und wechselst direkt hinein. Funktionen gehören wie Aliases nach ~/.bashrc.
Faustregel: Alias für eine reine Abkürzung, Funktion sobald Argumente, Pipes oder mehrere Befehle ins Spiel kommen.
Persistente Konfiguration sauber organisieren
Eine ~/.bashrc kann schnell auf mehrere hundert Zeilen anwachsen — Aliases, Funktionen, Prompt-Konfiguration, Tool-Init-Skripte, alles bunt durcheinander. Sauberer ist eine modulare Struktur, bei der du themenspezifische Dateien in einem Unterverzeichnis ablegst und sie automatisch einbindest.
# In ~/.bashrc am Ende:
if [ -d ~/.bashrc.d ]; then
for f in ~/.bashrc.d/*.sh; do
[ -r "$f" ] && . "$f"
done
unset f
fiIm Verzeichnis ~/.bashrc.d/ liegen dann Dateien wie 10-aliases.sh, 20-functions.sh, 30-prompt.sh, 40-tools.sh. Die Zahlen-Präfixe steuern die Lade-Reihenfolge. Alternativ verwenden manche Setups ~/.config/bash/ und folgen damit der XDG Base Directory Specification.
Spätestens wenn du diese Konfiguration auf mehreren Rechnern synchron halten willst, lohnt sich ein Blick auf Dotfiles-Verwaltung. Tools wie chezmoi, yadm oder ein einfaches Git-Repo mit Symlinks halten deine Shell-Umgebung über Hosts hinweg konsistent.
Häufige Fragen
Wo setze ich PATH-Erweiterungen?
In ~/.profile oder ~/.bash_profile, nicht in ~/.bashrc. Grund: GUI-Anwendungen und Login-Sessions lesen ~/.bashrc nicht, sondern nur die Login-Init-Files. Wenn du ~/.local/bin ergänzen willst, schreibe export PATH="$HOME/.local/bin:$PATH" in ~/.profile. Beim nächsten Login (oder nach source ~/.profile) ist der Pfad in der gesamten Sitzung verfügbar.
Warum sieht ssh meinen Alias nicht?
Aliases werden nur in interaktiven Shells eingelesen, und sie stehen üblicherweise in ~/.bashrc. Wenn du ssh host befehl aufrufst, startet eine nicht-interaktive Login-Shell, die ~/.bashrc überspringt. Lösung: Entweder den Befehl mit ssh -t host interaktiv ausführen, oder die nötigen Aliases in ~/.bash_profile definieren und vorher shopt -s expand_aliases setzen — Letzteres ist aber selten der Mühe wert.
Was passiert, wenn beide .profile und .bash_profile existieren?
Die Bash liest beim Login nur die erste vorhandene Datei in der Reihenfolge ~/.bash_profile, ~/.bash_login, ~/.profile. Existiert ~/.bash_profile, wird ~/.profile komplett ignoriert. Das ist eine häufige Falle: Du fügst etwas zu ~/.profile hinzu, aber ~/.bash_profile ist da und überschattet es. Prüfe mit ls -la ~/ | grep -E 'profile|bash', was tatsächlich existiert.
Warum wird die Shell-Variable in Skripten nicht erkannt?
Weil sie nicht exportiert ist. name=wert erzeugt nur eine Shell-Variable; ein Kind-Prozess wie ein Skript sieht sie nicht. Erst export name=wert (oder name=wert direkt vor dem Skript-Aufruf, etwa name=wert ./skript.sh) macht sie zur Umgebungsvariable und vererbt sie weiter.
Wie sehe ich, in welcher Shell-Variante ich gerade bin?
shopt -q login_shell && echo Login || echo Non-Login zeigt dir, ob es eine Login-Shell ist. Die Variable $- enthält die aktuellen Shell-Optionen — taucht dort ein i auf, ist die Shell interaktiv. Den Pfad der laufenden Shell findest du mit echo $0 (Shell-Name) oder ps -p $$ -o comm= (zuverlässiger bei Skripten).
Brauche ich source ~/.bashrc nach Änderungen?
Ja, wenn die Änderungen in der aktuellen Sitzung wirken sollen. Die Shell liest Init-Files nur beim Start. Mit source ~/.bashrc (oder kurz . ~/.bashrc) wird die Datei im Kontext der laufenden Shell ausgeführt, und neue Aliases, Variablen und Funktionen sind sofort verfügbar. Ein neues Terminal-Tab erledigt das automatisch.
Weiterführende Ressourcen
Externe Quellen
- Bash-Manpage, Sektion INVOCATION (man7.org) — autoritative Beschreibung, welche Init-Files wann gelesen werden
- GNU Bash-Handbuch — vollständige Referenz inkl. Startup-Files-Kapitel
- Arch Wiki: Environment variables — praxisnahe Übersicht zu Standard-Variablen und Persistenz
- XDG Base Directory Specification — Standardpfade für
XDG_CONFIG_HOMEundXDG_DATA_HOME
Verwandte Artikel
- Linux Variablen — Syntax, Sonderzeichen und Quoting im Detail
- Linux Shell — stdin, stdout, Pipes und Built-ins
- Linux PATH — wie die Shell Programme findet
- Linux Manpages — Hilfe direkt im Terminal