Was ist aktuell die beste Methode um Programme distributionsunabhängig auszuliefern?

5 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Kleine Werkzeuge kompiliere ich mir statisch in eine ELF ohne Section-Header.

Das hat den Effekt, dass die Binary auf allen Kerneln seit 1.x unverändert läuft, und du nur ein einziges Binary-File ausliefern musst.

Da du ohne Kopfstände aber nicht verhindern kannst, dass der Linker (libdl.so usw.) in Form von einiger Hand voll Pseudo-Bibliotheken geladen wird - was wieder Systemspezifisch ist - wird diese Methode für dich nicht praktikabel sein.

Dazu habe ich auch nichts im Netz gefunden, sondern mich selbst durch die Einstellungen für Compiler und Linker gequält.

Fakt ist, es ist möglich, eine einzige Binary zu erzeugen, die unverändert auf alten und zukünftigen Distributionen laufen wird, aber das wird hier den Rahmen bei weitem sprengen.

Eine weitere noch einfachere Möglichkeit ist, deinen Code in eine (statische oder dynamische) Bibliothek zu packen und ein leichtgewichtiges Makefile mit auszuliefern, welches eine Executable drum rum baut.

Die dritte und m. M. n. beste Möglichkeit wäre einfach ein Tarball und dem Endnutzer den Hinweis "make" zu geben.

Von Containern halte ich perösnlich nichts, da total monströs aufgeblasen. Das steht fast nie in einem Verhältnis zum Nutzen ... sehen die meisten Leute aber wohl anders.

Und Formate wie Snap & Co sind mir persönlich viel zu unsauber konzipiert, aber man kommt ja leider oft nicht drum herum.

Naja, musst du selbst eintscheiden, was du favorisierst, aber ich denke, am Ende wirst du bei Containern oder einem deiner oben genannten Formate landen. :)

Woher ich das weiß:Berufserfahrung

Ja ich glaub ich kompilier das einfach als Binary und lass einen Hinweis da, was für Abhängigkeiten benötigt werden.

Alles andere ist zumindest für „kleinere“ Programme zu viel des Guten.

1
@LiemaeuLP

Meistens sind die naheliegendsten Lösungen auch die besten. :)

1

Wenn man den Apologeten bei RH und Co. glauben darf, dann sind statische Executeables Pfui Bäh. Zumindest in Hinblick auf die (unnötige) Codereplikation kann ich das auf direkt nachvollziehen...

Wie sieht das eigentlich inzwischen mit static PIEs aus? Klappt das inzwischen ganz gut?

1
@KarlRanseierIII

Ja, mit neuen Compilern kann man PIEs bauen und inzwischen muss man nicht mehr zu 100% alles per Hand hacken, sondern die Compiler nehmen einem einen großen Teil der Arbeit ab.

So richtig schön flutscht das unter Linux (abgesehen von Android) aber ehrlich gesagt immer noch nicht. Ist eben (leider noch) kein Standardanwendungsfall wie bei einigen BSDs.

Ach und, wenn ich eine Software als Binary verteilen will, dazu nur ein ELF kopieren muss, und exakt Null Abhängigkeiten habe, dann können die Rothüte sagen was sie wollen ... da überwiegen einfach zu viele Vorteile, als dass ich Futter für den Paketmanager aufblase. :)

1

Hallo

Was ist aktuell eigtl die beste Methode, um Programme distributionsunabhängig auszuliefern?
  1. Wie schon seit eh und jeh, als Tarball → name.version.tar.gz
  2. Die zweitbeste Variante wäre dann Flatpack (Weil da jedes Paket seine Abhängigkeiten nochmal mit installiert, was konträr gegen die Philosophie ist, nämlich alles zu teilen. Damit kann es dann passieren das man 10x die glibc auf dem Rechner hat, womöglich in verschiedenen Versionen)
Gibts noch mehr?
  • Um Himmels Willen, noch mehr bringt nur noch mehr Verwirrung.
  • Bisher sind aus allen Versuchen ein gemeinsames Paketformat zu schaffen immer nur neue entstanden die mal mehr und mal weniger verbreitet sind (leider). Das am verbreitetsten zu nennende Paketformat ist wohl *.deb weil es eben alleine von Ubuntu 89 Forks gibt.

Linuxhase

Woher ich das weiß:Eigene Erfahrung – Ich benutze seit 2007 Linux und habe LPIC101 und LPIC102
Wie schon seit eh und jeh, als  Tarball → name.version.tar.gz

Naja, das geht aber auch nur mit statically linked binaries oder halt mit dem Quellcode (und das will man nicht, dafuer gibts ja Paketmanager ;))

2
distributionsunabhängig

reicht denn das aus? Kommen da nicht auch noch Kernel-Releases und Varianten anderer Pakete hinzu? In solchen Fällen nützen doch nicht mal die Quellpakete etwas, wenn sogar der Quellcode geändert werden muss und man nicht weiß wie.

Wie oft kommt es vor, nicht mal aus Quell-Paketen (mit Make-File) Binaries erzeugen zu können?

Da nützt es auch sehr wenig, z.B. eine andere Library zu installieren, die dann nicht zu anderen Paketen passt.

Gibts noch mehr?

Jau, Container.

Docker bietet sich da an und bringt dir u.A. folgende Vorteile:

  • Container laeuft dort wo Docker laeuft (im Regelfall also auch Cross-OS, nicht nur Cross-Distro)
  • Service Deployment wird unabhaengig vom Host
  • Service Config wird unabhaengig vom Host
  • Wartungsarbeiten zwischen Host und Service koennen schoen sauber getrennt werden
  • Deployment Zeiten sind eine ganze Ecke knackiger als per klassischem Paketmanagement
  • Zentraler "Hub" ist verfuegbar (geht auch self-hosted)

Disclaimer dazu aber: Das funktioniert bei vielen Desktop-Programmen nicht; sofern die Frage in diese Richtung ging ist meine Antwort quasi obsolet :p

Nur als Frage, da ich bisher nicht containern mußte (haha, doofes Wortspiel, schon klar), wie macht Docker das?

Muß die Applikation dann explizit für Docker umgeschrieben werden und gegen dessen Libs gelinkt werden. Oder wird dann eine ganze Distribution mitgepackt?

0
@KarlRanseierIII

Normalerweise nicht, es gibt eigentlich kaum "normale" Apps, die sich nicht in einem Container abbilden lassen.

Das Coole ist, dass Docker mit verschiedenen "Layern" arbeiten kann und es komplette Distros bereits containerized als Docker Image gibt.

Gelebte Praxis ist, dass man z.B. einfach von einem Ubuntu 18.04 Image "abspringt" und im Dockerfile dann sagt "hier bitte noch apt-get install apache2" und dann hat man seinen Apache Container (damit gibt man die ganze Dependency Hoelle einfach an einen Paketmanager seiner Wahl ab). Am Ende startet man einfach das Binary und solange das im Vordergrund lauffaehig ist, ist alles gut.

So kann man das mit "eigentlich" jedem Service machen; es gibt natuerlich Ausnahmen, z.B. wenn ein Service zwingend von systemd abhaengt (kann man zwar auch loesen, ist aber weird).

Atlassian packt z.B. mittlerweile auch ihre fetten Apps wie Jira oder Confluence in Container, das funktioniert sehr prima.

Docker selbst abstrahiert das soweit weg, dass man obiges Ubuntu + Apache Image auch auf einem Suse, RHEL oder eben Windows laufen lassen kann.

1
@barnim

Ich stelle mir das halt schwierig vor, wenn ich z.B. einen customized build gegen . musl oder newlib auf einem System mit glibc ausführen möchte und umgekehrt.

Deswegen frage ich mich halt, welchen Ansatz Docker hierbei verwendet.

0
@KarlRanseierIII

Bei Entwicklungsdingen bin ich mangels Wissen raus; aber grundsaetzlich wuerde ich sagen: Wenn du per Hand so ein Build System bauen kannst, kannst du das vermutlich auch als Container Image nachbauen.

Baut man sowas from Scratch oder nimmt man sich eine normale Distro mit glibc und bauts um? Falls letzteres, sollte es funktionieren in dem man sich eben so ein Distro Docker Image sucht, davon abspringt und dieselben Dinge tut, die man auch auf nem normalen Server tun wuerde. Dann haette man sein "Base newlib" Image und koennte von da weitermachen mit dem Software Zeug.

Was du auf dem Host System installiert hast, ist im Container nicht mehr wichtig.

Docker funktioniert nicht so wie z.B. OpenVZ, wo die Container auf den Libs vom Hostsystem sitzen.

1
@barnim
Baut man sowas from Scratch oder nimmt man sich eine normale Distro mit glibc und bauts um?

Sowohl als auch, bzw. wie mans gerne hätte. Wobei eine Koexistenz ohne seperate Toolchain schon schwierig ist.

Es war auch eher exemplarisch gedacht, wenns ans eingemachte geht, ein anderes mieses Beispiel, die libstdc++, die ist nämlich mit der Version von g++ vertaut und das gibt regelmässig dicke 'Backen', wenn ich mit einem g++ compile und auf einem anderen System dann eine andere libstdc++ (bzw. ein anderer g++) rumliegt.

Von icu und boost will ich eigentlich gar nicht erst anfangen :-D.

0
@KarlRanseierIII

Klingt aber so, als wuerde da Docker ein guter Ansatz sein. Du kapselst alles was irgendwie Custom ist einfach in einem Container Image und machst das so dort lauffaehig wo Docker selbst auch laufen kann.

Im besten Fall wirft dein Build Prozess dann schon ein fertiges Image mit entsprechendem Version-Tag hinten raus. In Jenkins und den anderen ueblichen Verdaechtigen kann man das ganz gut mit in die Pipeline bauen.

1
@barnim

Ja, nur läuft es darauf hinaus, daß in jedem Image das halbe System (in Hinblick auf libs) liegen muß - und da fragt man sich dann nach dem Nutzen.

Ich hatte da neulich ein schönes Beispiel, bereit für etwas Spaß :-)?

Ein NFS-Server verweigert den Dienst, ich erspare mir die exakten Details, aber, was war passiert?

Die Werzeuge (und daemons) nutzen einen Syscall, der nicht in allen Kernelversionen vorhanden ist. Dort wo der Syscall fehlt, emuliert die glibc diesen Syscall, bildet aber nur einen Teil der Funktionalität ab und lässt sonst den Call mit ENOSYS abblitzen. (Aber eben nicht per se, sondern in Abhängigkeit der Version der glibc).

Würde ich das in einen Container werfen ... dann habe ich eine Abhängigkeit der Funktionalität vom Kernel des später hostenden OS, oder aber ich muß eine glibc dazu packen, die das richtig handhabt, bzw. mehrere, je nachdem welcher Kernel später vorhanden ist.

Das hört sich dann schon etwas 'verfettet' an :-D.

0

Keine Ahnung, ehrlich gesagt, aber ist das überhaupt sinnvoll? Ich meine, damit sowas funktioniert, muß man ja alle Abhängigkeiten mitverpacken!?

Das ist ja wie das Windowsgeraffel :-P.

Das ist ja wie das Windowsgeraffel :-P.

Es ist sogar fast noch schlimmer.

Bei Windows gibt es immerhin einen de-facto Standard: Jedes Programm hat ein eigenes Verzeichnis und gut ist. (Es sei denn, da hat sich seit der XP-Ära was dran geändert. o.O)

Hier hingegen haben wir:

  • FlatPak
  • AppImage
  • Docker
  • usw...

P.S.: https://xkcd.com/927/ ^^

1

Was möchtest Du wissen?