Was ist BusyBox?
(specular.fi)- BusyBox ist ein Multicall-Binary, das mehrere Befehle in einer einzigen ausführbaren Datei bereitstellt; auch Alpines Standard-
wgetwird über BusyBox ausgeführt - In einem Alpine-Container war
/usr/bin/wgetkein echtes Binary, sondern ein symbolischer Link, der auf/bin/busyboxzeigt - Beim Start liest BusyBox den aufgerufenen Namen aus
argv[0]und bestimmt anhand des letzten Namensbestandteils im Pfad, welches Applet ausgeführt werden soll - Jedes Applet wird über seinen Namen gefunden und springt dann in die entsprechende
main-Funktion;wgetist inwget.cimplementiert und führt am Endewget_mainaus - Mit
busybox --listlassen sich die einkompilierten Befehle anzeigen; im Alpine-Beispiel werden 304 angezeigt, und jedes Utility wirkt wie eine abgespeckte Version
Funktionsweise von BusyBox
- BusyBox verwendet eine Multicall-Binary-Struktur, bei der mehrere Befehle in einer einzigen ausführbaren Datei bereitgestellt werden
- In einem Alpine-Container war
/usr/bin/wgetkeine echte ausführbare Datei, sondern ein symbolischer Link auf/bin/busyboxdocker run --rm -it alpine sh / # which wget /usr/bin/wget / # ls -lah /usr/bin/wget lrwxrwxrwx 1 root root 12 Apr 15 04:51 /usr/bin/wget -> /bin/busybox - In
/usr/binscheinen mehr als 130 ausführbare Dateien aus einem einzigen Binary zu stammen, was mit der Multicall-Binary-Struktur von BusyBox zusammenhängt - Beim Start übernimmt BusyBox den aufgerufenen Namen aus
argv[0], extrahiert nur den letzten Namensbestandteil des Pfads und entscheidet so, welches Applet ausgeführt werden sollapplet_name = argv[0]; if (applet_name[0] == '-') applet_name++; applet_name = bb_basename(applet_name); - Es funktioniert auch, den Applet-Namen explizit zu übergeben, etwa mit
busybox ls -1; wird ein nicht vorhandener Name angegeben, erscheintapplet not found/ # busybox ls -1 bin dev etc home / # busybox meheh meheh: applet not found
Aufbau der Applets und Installationsweise
- BusyBox sucht zunächst anhand des Namens das Applet und führt dann dessen
main-Funktion ausint applet = find_applet_by_name(name); // ... run_applet_no_and_exit(applet, name, argv); // ... xfunc_error_retval = applet_main[applet_no](argc, argv); - Jedes Applet besitzt eine eigene C-Datei;
wgetist inwget.cimplementiert - Die appletspezifischen Einstellungen sind in Form von Code-Kommentaren definiert; die
WGET-Konfiguration enthältwget (41 kb), die Standardaktivierung, einen Hilfetext als Utility zum nicht interaktiven Herunterladen von Dateien von HTTP- und FTP-Servern sowie das Build-Zielwget.o//config:config WGET //config: bool "wget (41 kb)" //config: default y //config: help //config: wget is a utility for non-interactive download of files from HTTP //config: and FTP servers. //applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_WGET) += wget.o - Das
wget-Applet springt letztlich inwget_mainint wget_main(int argc UNUSED_PARAM, char **argv) - BusyBox unterstützt auch Hardlinks; bei
busybox --install -ssteht-sfür das Erstellen symbolischer Linksbusybox --install -s - Die Liste der in die Kompilierung aufgenommenen Befehle lässt sich mit
busybox --listanzeigen; in der Alpine-Beispielumgebung werden 304 ausgegeben/ # busybox --list | wc -l 304 - Viele Befehle in Alpine fungieren wie eine Schnittstelle zu BusyBox-basierten Binaries, und jedes Utility wirkt im Vergleich zum vollständigen Original eher wie eine abgespeckte Version
1 Kommentare
Meinungen auf Lobste.rs
Die Antwort auf die zitierte Frage ist eher Neuimplementierung
Eine Einführung zu BusyBox gibt es unter https://busybox.net/about.html, und der Quellcode liegt unter https://github.com/vda-linux/busybox_mirror
Es nervt ziemlich, wenn ein Programm so tut, als hätte es einen anderen Namen als in Wirklichkeit
Am schlimmsten ist es, wenn man unter macOS
gccausführt und tatsächlich clang bekommt; PowerShell verhält sich ähnlich. Es wäre besser, einfach einen anderen Namen zu verwendenNixpkgs braucht viele Patches wie https://github.com/NixOS/nixpkgs/…, und selbst bekannte Projekte wie sqlite sind keine Ausnahme. macOS hat sich stattdessen offenbar einfach für den täuschenden Pfad entschieden
ccnichtEs gibt vermutlich viele Makefiles, in denen
gccfest verdrahtet ist, und in anderen Kontexten ist es ähnlich. Zum Beispiel prüfen viele bestehende Programme aufxterm-*in derTERM-Umgebungsvariable statt die korrekte Lösung über dieterminfo-Datenbank zu nutzen, daher funktioniert der Ansatz mit einem anderen Namen nichtWenn ich in einem Container seltsame Probleme diagnostiziere, nutze ich oft
podman cp /usr/bin/busybox-static somecontainer:/bintoybox hat eine ähnliche Struktur
Einige Tools scheinen von anderswo übernommen oder portiert worden zu sein, aber viele wurden für BusyBox neu implementiert; das Ziel ist, sie klein zu halten und nur eingeschränkte libc-Funktionen zu verwenden, damit sie beim statischen Linken klein kompiliert werden. Ein weiterer Vorteil ist, dass man diese Tools in Shell-Skripten wie Built-ins verwenden kann. Manche werden nicht per fork+exec, sondern per fork+jump ausgeführt, und einige lassen sich sogar ohne Fork als normaler Funktionsaufruf ausführen
Ergänzend dazu heißt es in Toybox on Wikipedia: „Toybox was started at the beginning of 2006 after Rob Landley stopped serving as maintainer of BusyBox due to a disagreement with Bruce Perens, the original creator of BusyBox.“
Technisch gesehen ist es eine Neuimplementierung. Wenn die Lizenz es erlaubt, wäre es allerdings nicht überraschend, wenn etwas Code aus der ursprünglichen großen Implementierung übernommen wurde
Laut der 'pedia: BusyBox wurde 1995 erstmals von Bruce Perens geschrieben und 1996 für seinen beabsichtigten Zweck als fertig erklärt. Das ursprüngliche Ziel war, ein vollständiges bootfähiges System, das als Rettungsdiskette und Installationsprogramm für die Debian-Distribution dient, auf eine einzige Diskette zu packen. Später entwickelte es sich zum De-facto-Standard-Kernset von User-Space-Werkzeugen für Embedded-Linux-Geräte und Installationsprogramme von Linux-Distributionen; da jede Linux-Binärdatei einige KB Overhead benötigt, spart das Zusammenfassen von mehr als 200 Programmen in einem einzigen erheblich Plattenplatz und Speicher
In diesem Zusammenhang ist auch Toybox in Struktur und Philosophie ähnlich, steht aber unter einer BSD-Lizenz. Ich erinnere mich, dass der Hauptentwickler Rob Landley meinte, mit einer für den kommerziellen Einsatz leichter akzeptablen Lizenz könnte es in Android-Geräte aufgenommen werden, und dann hätten alle Android-Smartphones und -Tablets das Potenzial, sich in eine Unix-ähnliche Entwicklungsumgebung zu verwandeln. Toybox scheint noch immer Teil von Android zu sein, aber ohne Werkzeuge aus darüberliegenden Schichten wie Termux lässt sich Android nicht besonders leicht wie ein Unix-System nutzen
Vor allem, wenn man bedenkt, dass Google jahrelang damit gedroht hat, Termux zu blockieren
Es gibt auch einen Windows-Port: https://github.com/rmyorston/busybox-w32
Durch die geringe Größe von BusyBox ist so ein Port realistischer. Allerdings scheint das heute etwas weniger relevant zu sein, weil man unter Windows inzwischen einfach Linux ausführen kann