/bin ist das Verzeichnis, in dem die essenziellen Kommandozeilen-Programme liegen, die jedes Linux-System zwingend braucht — ls, cp, mv, cat, grep, ps, kill, sh, bash und viele mehr. Historisch ist /bin derjenige Pfad, der schon vor dem Mounten von /usr verfügbar sein muss, damit das System überhaupt startfähig ist. Auf modernen Distributionen ist /bin heute meist ein Symlink auf /usr/bin (Usr-Merge), die Rolle als minimale Werkzeugkiste bleibt aber dieselbe.

Was steckt in /bin?

Im Kern enthält /bin die Programme, die für eine funktionierende Shell-Sitzung und einfache Systemwartung unverzichtbar sind. Das umfasst Datei- und Verzeichnis-Operationen, Text-Anzeige und -Manipulation, Prozess-Verwaltung und einige System-Werkzeuge.

KategorieTypische Programme
Datei- und Verzeichnis-Operationenls, cp, mv, rm, mkdir, rmdir, ln, chmod, chown, chgrp, touch, pwd
Text- und Datenanzeigecat, echo, printf, more, less, head, tail, grep, sed, sort, uniq
Shells und Skriptingsh, bash, dash, [, test, true, false
Prozesse und Signaleps, kill, killall, nice, wait
System-Informationhostname, uname, date, dmesg, df, du, mount, umount
Netzwerk-Basisping, hostname, oft auch nc (netcat)
Notfall-Helferdd, sync, cpio, tar, gzip, bzip2

Was du dort nicht findest: alles, was nicht für den Boot- oder Single-User-Modus essenziell ist. Texteditoren wie vim, Compiler, Skriptsprachen, Server-Daemons, Desktop-Software — all das gehört nach /usr/bin oder bei manueller Installation nach /usr/local/bin.

Auf einem typischen modernen System (Ubuntu 24.04, Debian 13, Fedora 41) findest du in /bin rund 150 bis 250 Einträge — größtenteils Coreutils plus die vom Linux Standard Base (LSB) geforderten Pflicht-Werkzeuge.

Der FHS-Standard und die Mindestanforderungen

Die Existenz und der Inhalt von /bin sind im Filesystem Hierarchy Standard (FHS) spezifiziert — derselbe Standard, der auch /etc, /usr, /var und Co. definiert. Die aktuelle FHS-Version 3.0 schreibt für /bin zwei Eigenschaften fest:

  1. /bin muss zur Verfügung stehen, damit Single-User-Maintenance möglich ist — also auch dann, wenn /usr (noch) nicht gemountet ist.
  2. /bin enthält Befehle, die alle Benutzer verwenden können müssen, nicht nur Administratoren.

Die FHS legt eine Mindestliste an Befehlen fest, die in /bin vorhanden sein müssen, sofern das jeweilige Programm überhaupt installiert ist:

FHS-Pflicht-BefehleZweck
cat, chgrp, chmod, chown, cp, dateGrundlegende Datei- und Datums-Operationen
dd, df, dmesg, echo, false, hostnameLow-Level-Datenverarbeitung, System-Info
kill, ln, login, ls, mkdir, mknod, more, mountProzesse, Verzeichnisse, Mounts
mv, ps, pwd, rm, rmdir, sed, sh, stty, suDateien, Prozess-Anzeige, Shell, User-Switch
sync, true, umount, unameDisk-Sync, Truthy/Falsy, Unmount, Kernel-Version

Distributionen erweitern die FHS-Liste meist um GNU-Coreutils-Standards wie head, tail, sort, uniq, printf oder Bash-spezifische Werkzeuge. Eine FHS-konforme Distribution darf zusätzliche Programme in /bin ablegen, muss aber die Pflicht-Liste enthalten.

Bash FHS-Mindestbefehle auf dem aktuellen System prüfen
# Pflicht-Befehle gegen das tatsächliche /bin abgleichen
for cmd in cat chgrp chmod chown cp date dd df dmesg echo \
           false hostname kill ln login ls mkdir mknod more \
           mount mv ps pwd rm rmdir sed sh stty su sync true \
           umount uname; do
    command -v "$cmd" >/dev/null || echo "FEHLT: $cmd"
done

Auf einem voll installierten Desktop-System gibt diese Schleife normalerweise nichts aus — alle Pflicht-Befehle sind vorhanden. Auf einem minimalen Container-Image (alpine, busybox) kann durchaus etwas fehlen, weil dort viele „Befehle” als Symlinks auf busybox realisiert sind.

/bin vs /sbin vs /usr/bin vs /usr/local/bin

Die FHS sieht insgesamt vier Binary-Verzeichnisse vor, die sich nach Zielgruppe und Quelle unterscheiden. Wer einmal versteht, wer wo hingehört, weiß auch, wo er ein bestimmtes Programm suchen muss — und wo eigene Skripte abgelegt werden sollten.

PfadZielgruppeInhaltBeispiel
/binAlle NutzerEssenzielle Kommandos, im Single-User-Modus verfügbarls, cat, cp
/sbinAdministrator (root)Systemverwaltung, Netzwerk-Setup, Filesystem-Toolsfdisk, mount, iptables, ip
/usr/binAlle NutzerDistributions-Software, Anwendungen, große Toolsvim, python3, git, firefox
/usr/sbinAdministratorDaemons, weitere System-Toolssshd, postfix, nginx
/usr/local/binAlle NutzerManuell installierte Software (nicht vom Paketmanager)Selbst kompilierte Tools, Helper-Skripte
/usr/local/sbinAdministratorManuell installierte Admin-ToolsEigene Backup-Skripte

Die Aufteilung folgt zwei Achsen: Nutzergruppe (alle vs. nur root) und Quelle (essenziell + Distribution vs. lokal/manuell installiert).

In der Praxis steht der PATH auf der meisten Distributionen so, dass /usr/local/bin vor /usr/bin durchsucht wird — eigene Builds übersteuern damit automatisch eine eventuell vorinstallierte Distributions-Version. Für Admin-Skripte, die nicht aus dem Paketmanager kommen, ist /usr/local/sbin der richtige Ort.

Bash Wo liegt ein bestimmtes Programm? — type, which, command
type ls
# ls is aliased to `ls --color=auto'
type -a python3
# python3 is /usr/bin/python3
# python3 is /usr/local/bin/python3   ← lokale Version steht vor distros

which mount
# /usr/bin/mount   ← nach Usr-Merge effektiv /bin

command -v fdisk
# /usr/sbin/fdisk

ls -la /sbin /usr/sbin | head -20

Hinweis: Manche Distributionen (z. B. Arch Linux) haben /sbin ebenfalls per Symlink auf /usr/bin zusammengelegt — der konzeptionelle Unterschied „nur für root” wird dann nur noch durch Datei-Berechtigungen (z. B. fehlende Lese- und Ausführungsrechte für Nicht-Root-Nutzer) und nicht mehr durch den Pfad ausgedrückt.

Usr-Merge: warum heute alles auf /usr/bin zeigt

Auf den meisten aktuellen Distributionen ist /bin heute schlicht ein Symlink auf /usr/bin — und ebenso /sbin → /usr/sbin, /lib → /usr/lib. Diese Vereinheitlichung wird Usr-Merge genannt und wurde zwischen 2012 und 2024 sukzessive umgesetzt:

DistributionUsr-Merge ab
FedoraVersion 17 (2012) — erster Vorreiter
Arch Linux2012, vollständig 2013
openSUSE13.2 (2014)
Solusseit Beginn (2014)
Ubuntu19.04 (2019)
RHEL / CentOS9 (2022)
Debian12 „Bookworm” (2023) verpflichtend
Alpine Linuxweitgehend, seit Anfang

Der Symlink ist absichtlich auf der Verzeichnis-Ebene gesetzt — er leitet jeden Zugriff um:

Bash Usr-Merge sichtbar machen
ls -la / | grep -E '^l'
# lrwxrwxrwx 1 root root  7 ... bin -> usr/bin
# lrwxrwxrwx 1 root root  7 ... lib -> usr/lib
# lrwxrwxrwx 1 root root  9 ... lib32 -> usr/lib32
# lrwxrwxrwx 1 root root 10 ... lib64 -> usr/lib64
# lrwxrwxrwx 1 root root  8 ... sbin -> usr/sbin

readlink /bin
# usr/bin

# Effektiv die gleiche Datei
stat /bin/ls /usr/bin/ls | grep Inode
# Inode: 12345
# Inode: 12345

Inhaltlich ändert der Usr-Merge nichts — beide Pfade zeigen auf dieselben Programme. Der eigentliche Gewinn liegt in der Wartbarkeit auf System-Ebene:

  • Atomare Updates und Snapshots. Wenn /usr ein eigener Mount-Punkt ist (etwa als read-only Subvolume bei Btrfs oder als image-basiertes Update bei Fedora Silverblue, NixOS, OpenSUSE MicroOS), ist es deutlich einfacher, das gesamte Userspace-Stage atomar zu tauschen, ohne dass /bin oder /lib in den Root-Filesystem-Bereich „lecken”.
  • Cross-Distribution-Kompatibilität. Skripte und Container-Images können sich auf einen einzigen Pfad stützen — der Shebang #!/usr/bin/env bash funktioniert überall, #!/bin/bash ebenfalls (über den Symlink).
  • Boot- und Init-Vereinfachung. Im Zeitalter von initramfs und systemd ist die alte Trennung „erst /, dann /usr mounten” technisch obsolet. Ein vereinheitlichter Userspace passt zur tatsächlichen Boot-Reihenfolge moderner Systeme.

Was nicht funktioniert: der Versuch, auf einem Usr-Merged-System eine Datei nur in /bin und nicht in /usr/bin abzulegen — der Symlink macht das physikalisch unmöglich. Skripte oder Buildsysteme, die das versuchen, müssen angepasst werden.

Boot-Reihenfolge und Single-User-Modus

Der historische Grund für die strikte Trennung zwischen /bin und /usr/bin lag in der Boot-Reihenfolge alter Unix-Systeme:

  1. Das Root-Filesystem (/) wurde gemountet — mit /bin, /sbin, /etc, /lib.
  2. Das System startete in den Single-User-Modus (Runlevel 1, „maintenance mode”) und lief nur mit den Programmen aus /bin und /sbin.
  3. Erst danach wurde /usr aus einer eventuell separaten Partition gemountet — /usr/bin wurde verfügbar.
  4. Das System ging in den Multi-User-Modus über (Runlevel 3 oder 5).

Diese Reihenfolge erforderte zwingend, dass alle Werkzeuge zur System-Reparatur (also: Filesystem prüfen, Konfiguration korrigieren, Backup einspielen) in /bin und /sbin lagen — Werkzeuge aus /usr/bin standen schlicht nicht zur Verfügung.

In modernen Linux-Systemen mit initramfs und systemd ist diese Trennung weitgehend obsolet:

  • Das initramfs (eine kleine, in den Hauptspeicher geladene RAM-Disk mit eigenem Mini-Userspace, oft auf BusyBox-Basis) übernimmt das Mounten aller Filesysteme — /usr ist von Anfang an verfügbar, sobald das eigentliche System startet.
  • systemd kennt keinen klassischen Runlevel mehr; stattdessen gibt es Targets wie rescue.target und emergency.target. Diese laufen mit dem vollen Userspace (inklusive /usr/bin).
  • Der Single-User-Modus existiert noch als Fallback (systemctl rescue oder Boot-Parameter systemd.unit=rescue.target), bringt aber den kompletten /usr-Stack mit.

Trotzdem behalten die Pfade ihre Rolle — und in Embedded-Systemen, Routern, BusyBox-basierten Containern und alten oder konservativen Systemen (z. B. einigen BSDs) ist die ursprüngliche Trennung weiter relevant.

Praxis: /bin auf deinem System inspizieren

Ein paar nützliche Kommandos, um zu verstehen, was auf deinem konkreten System los ist:

Bash Inhalt und Größe von /bin auf einen Blick
# Wieviele Programme stecken in /bin?
ls /bin | wc -l

# Größte Binaries (z. B. zur Inspektion vor Cleanup)
du -ah /bin | sort -hr | head -20

# Alle Symlinks in /bin auflisten — viele Programme sind nur
# Aliase, etwa awk → gawk oder vi → vim.basic
find /bin -maxdepth 1 -type l -printf '%f -> %l\n'

# Alphabetische Liste mit Datei-Typ
file /bin/* 2>/dev/null | head -20

Die Datei-Größe der Binaries ist auf modernen Systemen größtenteils wenige hundert KB pro Programm — der überwältigende Anteil sind die Coreutils, die statisch verlinkte Versionen mancher Programme sind aber merklich größer.

Bash Welches Paket bringt welche Datei nach /bin?
# Debian/Ubuntu: dpkg-Datenbank fragen
dpkg -S /bin/ls
# coreutils: /bin/ls

# Fedora/RHEL: rpm fragen
rpm -qf /bin/ls
# coreutils-9.5-1.fc41.x86_64

# Arch: pacman fragen
pacman -Qo /bin/ls
# /usr/bin/ls is owned by coreutils 9.5-1

Praktisch bei Debugging: kommt ein bestimmtes Werkzeug von der Distribution oder von einem Drittanbieter? Der Paketmanager kennt jede Datei in /bin und sagt dir, zu welchem Paket sie gehört.

Bash SUID-Programme in /bin finden
# Welche Programme in /bin haben SUID gesetzt?
find /bin -maxdepth 1 -perm -4000 -type f -ls 2>/dev/null
# ... -rwsr-xr-x ... /bin/su
# ... -rwsr-xr-x ... /bin/mount
# ... -rwsr-xr-x ... /bin/umount
# ... -rwsr-xr-x ... /bin/ping     ← bei manchen Distributionen

SUID („set user ID”) sorgt dafür, dass das Programm mit den Rechten des Datei-Owners (meist root) statt mit denen des aufrufenden Nutzers läuft. Klassisches Beispiel ist su — ohne SUID könnte ein normaler User nicht in den Root-Account wechseln. Im Hardening solltest du diese Liste regelmäßig prüfen, weil jeder SUID-Eintrag eine potenzielle Privilege-Escalation-Quelle ist.

Interessantes

Eigene Skripte gehören NICHT in /bin

Auch wenn man der Versuchung ausgesetzt sein könnte: Selbstgeschriebene Helper-Skripte landen nicht in /bin. Erstens überschreibt das nächste System-Update den Inhalt potenziell, zweitens vermischst du Distribution-Software mit lokaler. Der korrekte Pfad ist /usr/local/bin für alle User oder ~/.local/bin für nur den eigenen User — beide stehen im PATH und werden vor /usr/bin gefunden.

Der Shebang #!/bin/sh ist kein Bash

Auf vielen Distributionen ist /bin/sh ein Symlink auf dash (Debian, Ubuntu) oder bash (Arch, openSUSE) — manchmal sogar auf mksh (Android-Welt). Skripte mit #!/bin/sh müssen sich strikt an POSIX halten, sonst brechen sie auf einem dash-System. Bash-Spezifika wie Arrays oder [[ ... ]] brauchen explizit #!/bin/bash.

busybox liefert eine Mini-/bin in einem Binary

Embedded-Systeme, Recovery-Images und Container wie Alpine Linux nutzen oft BusyBox — ein einziges Binary, das Hunderte Mini-Implementierungen klassischer Unix-Befehle vereint. ls, cp, mv usw. sind dort Symlinks auf /bin/busybox. Der Vorteil: extrem klein (1–2 MB für die komplette Werkzeugkiste), der Preis: viele Optionen fehlen oder verhalten sich anders als die GNU-Versionen.

Statisch vs. dynamisch verlinkte /bin-Programme

Standardmäßig sind die Programme in /bin dynamisch gegen die System-Bibliotheken in /lib und /usr/lib gelinkt. Manche Distributionen liefern aber wichtige Programme zusätzlich als statisch gelinkte Variante (z. B. bash-static, ldconfig.real) — sie funktionieren auch dann noch, wenn das Linker-System gerade kaputt ist. Mit ldd /bin/ls siehst du die Abhängigkeiten eines Programms.

ping ist auf neueren Systemen kein SUID mehr

Lange Zeit war /bin/ping SUID-root, weil das Programm einen RAW-Socket öffnen muss. Auf neueren Linux-Kernels (≥ 4.3) gibt es stattdessen Linux Capabilities: cap_net_raw=p reicht, ein klassisches SUID ist nicht mehr nötig. Distributionen wie Fedora und Ubuntu sind bereits umgestellt — getcap /bin/ping zeigt die effektiven Capabilities.

Der Pfad /bin existiert auch noch ohne Usr-Merge

Sehr alte Embedded-Systeme, statisch konstruierte Container oder einige BSD-Derivate (FreeBSD, OpenBSD) trennen weiterhin strikt zwischen /bin und /usr/bin — kein Symlink, sondern echte Verzeichnisse. Beim Schreiben portabler Skripte sollte man sich auf /usr/bin/env <prog> als Shebang verlassen, nicht auf hartkodierte Pfade.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Verzeichnisstruktur

Zur Übersicht