Der Zweck dieser Frage ist es, eine Neugierde zu beantworten und nicht ein bestimmtes Computerproblem zu lösen. Die Frage ist: Warum sind obligatorische POSIX-Dienstprogramme nicht allgemein in Shell-Implementierungen integriert?
Ich habe zum Beispiel ein Skript, das im Grunde genommen ein paar kleine Textdateien liest und überprüft, ob sie richtig formatiert sind, aber es dauert 27 Sekunden, bis sie auf meinem Computer ausgeführt werden, da ein erheblicher Teil der Zeichenfolgen bearbeitet wird. Diese String-Manipulation bringt Tausende neuer Prozesse hervor, indem verschiedene Dienstprogramme aufgerufen werden, daher die Langsamkeit. Ich bin mir ziemlich sicher , dass , wenn einige der Dienstprogramme in gebaut wurden, nämlich grep
, sed
, cut
, tr
, und expr
dann das Skript in einem zweiten laufen würde oder weniger (basierend auf meiner Erfahrung in C).
Es scheint viele Situationen zu geben, in denen der Einbau dieser Dienstprogramme den Unterschied zwischen einer akzeptablen Leistung einer Lösung in Shell-Skripten ausmacht.
Offensichtlich gibt es einen Grund, warum diese Dienstprogramme nicht integriert wurden. Wenn Sie möglicherweise eine Version eines Dienstprogramms auf Systemebene verwenden, wird vermieden, dass mehrere ungleiche Versionen dieses Dienstprogramms von verschiedenen Shells verwendet werden. Ich kann mir wirklich nicht viele andere Gründe vorstellen, um den Aufwand für die Erstellung so vieler neuer Prozesse zu verringern, und POSIX definiert die Dienstprogramme so genau, dass es kein großes Problem zu sein scheint, unterschiedliche Implementierungen zu haben, solange es sich um POSIX handelt konforme. Zumindest kein so großes Problem wie die Ineffizienz so vieler Prozesse.
printf
usw.) in Shells integriert, wenn sie als nützlich genug erachtet wurden.awk
ein obligatorisches Dienstprogramm in POSIX und besonders gut geeignet (das, sehr schnell ist) Skripte zu implementieren , dass Sie sonst implementieren könnten mitsed
,cut
,tr
,grep
, undexpr
in einem Shell - Skript.Antworten:
Von Shell-Skripten wird nicht erwartet, dass sie mit dieser Geschwindigkeit ausgeführt werden. Wenn Sie die Geschwindigkeit Ihres Skripts verbessern möchten, versuchen Sie es in Perl. Wenn das immer noch zu langsam ist, müssen Sie zu einer statisch typisierten Sprache wie Java oder C wechseln oder ein C-Modul für Perl schreiben, das die Teile ausführt, die zu langsam sind.
Shell ist die erste Ebene des Prototyping. Wenn Sie das Konzept mit Shell beweisen können, wechseln Sie zu einer besseren Skriptsprache, mit der mehr Grenzen überprüft werden können, als für die Shell erforderlich wären.
Es wird erwartet, dass ein Unix-Betriebssystem viele kleine Programme enthält, die genau definierte Aufgaben ausführen, die ein größeres Bild ergeben. Dies ist eine gute Sache, da es größere Programme unterteilt. Schauen Sie sich zum Beispiel qmail an und vergleichen Sie das mit sendmail. qmail besteht aus vielen Programmen:
http://www.nrg4u.com/qmail/the-big-qmail-picture-103-p1.gif
Wenn Sie den Netzwerkdämon ausnutzen, können Sie den Warteschlangenmanager nicht ausnutzen.
quelle
cd
oder eingebaut sindpwd
.cd
ist eingebaut - und muss es auch sein, da das Ändern des Arbeitsverzeichnisses in einem Unterprozess keine Auswirkungen auf übergeordnete Prozesse hat.Da POSIX - kompatibel sein wird ein System benötigt 1 die meisten Dienstprogramme als Standalone - Befehle zur Verfügung zu stellen.
Wenn sie eingebaut würden, müssten sie an zwei verschiedenen Orten existieren, innerhalb und außerhalb der Hülle. Natürlich wäre es möglich, die externe Version zu implementieren, indem ein Shell-Skript-Wrapper für das eingebaute Skript verwendet wird, aber dies würde Nicht-Shell-Anwendungen benachteiligen, die die Dienstprogramme aufrufen.
Beachten Sie, dass BusyBox den von Ihnen vorgeschlagenen Weg eingeschlagen hat, indem Sie viele Befehle intern implementiert und die eigenständige Variante über Links zu sich selbst bereitgestellt haben. Ein Problem ist, dass der Befehlssatz zwar ziemlich umfangreich sein kann, die Implementierungen jedoch häufig eine Teilmenge des Standards darstellen und daher nicht kompatibel sind.
Beachten Sie, dass auch zumindest
ksh93
,bash
undzsh
geht weiter durch benutzerdefinierte Methoden für den laufend Shell dynamisch Last builtins von gemeinsam genutzten Bibliotheken bereitstellt. Technisch gesehen steht dann nichts mehr im Wege, alle POSIX-Dienstprogramme als Builtins zu implementieren und verfügbar zu machen.Schließlich ist das Erzeugen neuer Prozesse mit modernen Betriebssystemen ein recht schneller Vorgang geworden. Wenn Sie wirklich von einem Leistungsproblem betroffen sind, gibt es möglicherweise einige Verbesserungen, um die Ausführung Ihrer Skripts zu beschleunigen.
1 POSIX.1-2008
quelle
fork
nicht folgenden Benutzer erstellt wurdenexec
.fork
ist heutzutage eine sehr leichte Operation im Vergleich zuexec
.nofork
builtins mit etwa 10x weniger Overhead alsnoexec
builtins gemessen, was wiederum ~ 5x weniger Overhead hatte als fork + exec einer separaten Binärdatei. Definitionen gemäß unix.stackexchange.com/a/274322/29483 Es ist interessant, dass die Busybox nichtnofork
alles kann, obwohl ich weiß, dass ein Teil des Busybox-Codes dadurch verkürzt wird, dass der Speicher nicht aufgeräumt wird.Von dem BASH - Referenzhandbuch ,
Wie Sie sicher gehört haben, stützt sich die UNIX-Philosophie in hohem Maße auf mehrere Anwendungen, die alle über eingeschränkte Funktionen verfügen. Jeder Einbau hat einen sehr guten Grund, warum er eingebaut ist. Alles andere ist es nicht. Ich denke, eine interessantere Klasse von Fragen ist "warum genau ist
pwd
eingebaut?".quelle
cd
wäre ein besseres Beispiel für etwas, das sich nicht als separates Tool implementieren lässt.cd
muss eingebaut werden,pwd
nicht. Warum haben sich diebash
Implementierer dafür entschieden, es aufzunehmen?/bin/bash
existiert, ist aber noch eingebaut. Die Liste der eingebauten Funktionen finden Sie unter gnu.org/software/bash/manual/html_node/…Die Jungs von AT & T haben sich dasselbe gefragt
Wenn Sie sich die Geschichte des AT & T-Software-Toolkits ansehen (das derzeit auf github ruht, seit das Kernteam abgereist ist), ist dies genau das, was es mit der AT & T-Korn-Shell, auch bekannt als ksh93, getan hat.
Leistung war immer ein Teil der Motivation für die ksh93-Betreuer, und beim Erstellen von ksh können Sie viele gängige POSIX-Dienstprogramme als dynamisch geladene Bibliotheken erstellen. Indem Sie diese Befehle an einen Verzeichnisnamen binden
/opt/ast/bin
, können Sie steuern, welche Version des Befehls verwendet wird, basierend auf der Position dieses Verzeichnisnamens in$PATH
.Beispiele:
Die vollständige Liste finden Sie im Archiv von github ast .
Beachten Sie, dass die meisten Ast-Tools ihre eigene Provenienz haben und sich stark von den allgemeineren Gnu-Implementierungen unterscheiden. Das AT & T-Forschungsteam hat die offiziellen Standards eingehalten. Auf diese Weise wurde Interoperabilität erreicht, wenn Code nicht freigegeben werden konnte.
quelle
Wir haben also keine Ressourcen in die Optimierung des ursprünglichen Tools gesteckt, um jedem spezifischen Wunsch gerecht zu werden. Ich denke, wir müssen erklären, wie viel die Umsetzung dieses spezifischen Wunsches gekostet hätte.
das ist eine schlechte Annahme :-P.
Post-POSIX-Systeme werden aus guten Gründen immer leistungsfähiger und praktischer. als nachträglicher Standard holt es nie wirklich auf.
Ubuntu bemühte sich, zu einer reduzierten POSIX-Shell für Skripte zu wechseln, um den alten System V-Startvorgang zu optimieren. Ich sage nicht, dass es fehlgeschlagen ist, aber es hat viele Fehler ausgelöst, die bereinigt werden mussten: "bashisms", Skripte, die unter der
/bin/sh
Annahme ausgeführt wurden, dassbash
Funktionen verfügbar waren.POSIX sh ist keine gute Programmiersprache für allgemeine Zwecke. Sein primärer Zweck ist auch ein interaktiv Shell zu arbeiten. Denken Sie daran, dass Sie sich einem Turing-Tarpit nähern, sobald Sie beginnen, Ihre Befehle in einem Skript zu speichern . Es ist beispielsweise nicht möglich, Fehler in der Mitte einer normalen Pipeline zu erkennen .
bash
hinzugefügtset -o pipefail
, aber dies ist nicht in POSIX.Ähnliche nützliche, aber nicht standardisierte Funktionen werden von fast jedem Dienstprogramm bereitgestellt, das komplexer ist als
true
.Für die Aufgabenklasse, die Sie skizzieren, können Sie eine grobe Linie zu Awk, Perl und heutzutage zu Python ziehen. Verschiedene Tools wurden erstellt und unabhängig voneinander weiterentwickelt. Würden Sie zB erwarten, dass GNU Awk in eine libutilposixextended subsumiert wird?
Ich sage nicht, dass wir jetzt einen allgemein besseren Ansatz haben, auf den ich Sie hinweisen kann. Ich habe eine Schwäche für Python. Awk ist überraschend mächtig, obwohl ich frustriert war, dass einige Funktionen spezifisch für GNU Awk sind. Der Punkt ist jedoch, dass die Verarbeitung einer großen Anzahl von Zeichenfolgen einzeln (vermutlich aus Zeilen der Dateien) kein Entwurfsziel der POSIX-Shell war.
quelle
cat -@fnord foo
die Shell entscheiden, dass, da sie nicht weiß, was-@
bedeutet, dass der eigentliche Befehlcat <foo >bar
aufgerufen werden muss, nur die Shell jedoch keinen weiteren Prozess auslösen muss.Es stellt sich auch die Frage: In welche Shell würden Sie sie einbauen?
Die meisten Unix / Linux-Systeme haben mehrere verschiedene Shells, die unabhängig voneinander entwickelt werden (sh / bash / korn / ???). Wenn Sie die Tools in die Shell einbauen, erhalten Sie für jede Shell eine andere Implementierung dieser Tools. Dies würde Overhead verursachen und Sie könnten abhängig von der Shell, die Sie zum Aufrufen verwendet haben, mit unterschiedlichen Funktionen / Fehlern in grep enden.
quelle
Viele haben gut geantwortet. Ich möchte diese Antworten nur beglückwünschen. Ich denke, die UNIX-Philosophie ist, dass ein Tool eines tun und es gut machen sollte. Wenn man versucht, ein umfassendes Werkzeug zu entwickeln, ist das viel mehr Anlass zum Scheitern. Wenn Sie die Funktionalität auf diese Weise einschränken, erhalten Sie einen zuverlässigen Werkzeugsatz.
Überlegen Sie auch, ob Funktionen wie sed oder grep in die Shell integriert sind. Wäre es dann so einfach, sie über die Befehlszeile aufzurufen, wenn Sie möchten?
Betrachten Sie abschließend, dass einige der Funktionen, die Sie in BASH haben möchten, in BASH enthalten sind . Beispielsweise wird die Fähigkeit zum RE-Matching in BASH mithilfe des binären Operators = ~ implementiert (siehe Shell-Grammatik in der Manual Page , um genauer auf die Diskussion des Konstrukts [[]] für if zu verweisen ). Angenommen, ich suche in einer Datei nach 2 hexadezimalen Ziffern:
Informationen zur sed-ähnlichen Funktionalität finden Sie unter Parametererweiterung in der Überschrift Erweiterung derselben Manpage. Sie werden eine Fülle von Dingen sehen, die an sed erinnern. Ich verwende sed am häufigsten, um eine Änderung des Ersetzungstyps in Text vorzunehmen. Aufbauend auf dem oben Gesagten:
Am Ende ist das obige "besser" als?
quelle
Das ist wohl ein historischer Unfall.
Als UNIX Ende der 1960er und Anfang der 1970er Jahre erstellt wurde, verfügten Computer bei weitem nicht über so viel Arbeitsspeicher wie heute. Zu dieser Zeit wäre es möglich gewesen, all diese Funktionen als Shell-Built-in zu implementieren, aber aufgrund von Speicherbeschränkungen hätten sie den Umfang der Funktionen, die sie implementieren könnten, einschränken müssen, oder es bestünde das Risiko, nicht genügend Arbeitsspeicher zu haben und / oder den Papierkorb auszutauschen Probleme.
Auf der anderen Seite könnten sie durch Implementieren der gegebenen Funktionalität als separate Programme und durch Erleichtern der beiden erforderlichen Systemaufrufe zum Starten eines neuen Prozesses eine Skriptumgebung erstellen, die diese Probleme nicht aufweist und die immer noch zumutbar ist Geschwindigkeit.
Natürlich, wenn diese Dinge als separate Prozesse eingeführt werden, um sie von Programmen Menschen beginnen, die nicht Granaten, und dann wie , dass sie bleiben müssen, oder plötzlich das alles Software beginnt zu brechen.
Das soll nicht heißen, dass Sie einige Funktionen nicht zweimal implementieren können, und in der Tat implementieren einige Shells einige Funktionen, die ein externes Programm als eingebaute Shell sein sollen. zB implementiert bash den
echo
Befehl als eingebauten Befehl, aber es gibt auch einen/usr/bin/echo
quelle