Warum ist echo eine eingebaute Shell?


34
$ which echo
echo: shell built-in command.
$ which ls
/bin/ls
$ which cat
/bin/cat

Warum ist Echo kein unabhängiges Dienstprogramm wie ls, ps, catetc? Warum ist es Shell-spezifisch? Irgendwelche guten Gründe?


5
Beachten Sie, dass dies muschelspezifisch ist. ZSH baut es ein, BASH nicht.
tsvallender

21
@tsv: Ganz echosicher ist ein Bash eingebaut. Tatsächlich ist es in jede wichtige moderne Hülle eingebaut.
Bis auf weiteres angehalten.

Antworten:


71

Es gibt zwei Klassen von Buildins:

  1. Einige Befehle müssen in das Shell-Programm selbst eingebaut werden, da sie nicht funktionieren, wenn sie extern sind.

    cdist eines davon, da es, wenn es extern wäre, nur sein eigenes Verzeichnis ändern könnte; es konnte sich nicht auf das aktuelle Arbeitsverzeichnis der Shell auswirken. (Siehe auch: Warum ist cdkein Programm? )

  2. Die andere Klasse von Befehlen ist nur aus Effizienzgründen in die Shell integriert.

    Der Mann Seite hat einen Abschnitt über builtins , die erwähnt , und als Beispiele für Befehle in dieser Klasse.dash printfechotest

Unix-Systeme haben immer separate ausführbare Dateien für Befehle in dieser zweiten Klasse enthalten. Diese separaten ausführbaren Dateien sind weiterhin auf jedem von mir verwendeten Unixy-System verfügbar, obwohl sie auch in jede Shell integriert sind, die Sie wahrscheinlich verwenden. (Für POSIX müssen diese ausführbaren Dateien vorhanden sein.)

Ich glaube echo, dass die Shell in AT & T Unix System V Release 3.1 eingebaut wurde. Ich stütze mich darauf, dass zwei verschiedene Ausgaben von Handbüchern für Unix-Systeme der AT & Ts 3B1-Serie verglichen werden . Jemand hat freundlicherweise 1986 Ausgaben dieser Handbücher gescannt und online gestellt . diese entsprechen der Originalversion von SVR3. Sie können sehen, dass dies echonicht in der Liste auf Seite 523 des UNIX System V-Benutzerhandbuchs, Band II , aufgeführt ist, wo Sie es erwarten würden, wenn der Befehl in die Shell integriert wäre. In meiner lokalen Papierkopie des SVR3.1 Handbücher von 1987, echo wird in diesem Abschnitt des Handbuch aufgeführt.

Ich bin mir ziemlich sicher, dass dies keine Innovation von Berkeley CSRG ist , die AT & T nach Hause gebracht hat. 4.3BSD erschien im selben Jahr wie SVR3, 1986, aber wenn Sie sich die sh.1-Manpage von 4.3BSD ansehen , sehen Sie, dass diese echonicht in der Liste der eingebauten Befehle im Abschnitt "Spezielle Befehle" enthalten ist. Wenn CSRG dies getan hat, möchten wir eine dokumentierte Quelle, um dies zu beweisen.

An diesem Punkt werden Sie sich vielleicht fragen, ob echodie Shell früher als SVR3.1 eingebaut wurde und ob diese Tatsache bis dahin einfach nicht dokumentiert war. Der neueste für mich verfügbare Pre-SVR3 AT & T Unix-Quellcode befindet sich im PDP-11 System III-Tarball , in dem sich der Bourne-Shell-Quellcode befindet. Sie werden es nicht echoin der eingebauten Befehlstabelle finden, die sich in befindet /usr/src/cmd/sh/msg.c. Basierend auf den Zeitstempeln in dieser Datei beweist dies, dass echoes 1980 mit Sicherheit keine Shell gab.


Trivia

Das gleiche Verzeichnis enthält auch eine Datei mit dem Namen, builtin.cdie für diese Frage keine Informationen enthält, aber wir finden diesen interessanten Kommentar:

/*      
    builtin commands are those that Bourne did not intend
    to be part of his shell.
    Redirection of i/o, or rather the lack of it, is still a
    problem..
*/      

Auf Seite 385 des von Ihnen erwähnten SysV UM, Vol II, gibt es den eingebauten printBefehl für ksh, der sich wie folgt verhält echo. Dieser Befehl ist auch in so etwas wie AT & T Unix SVR4 2.1 i386 von ISC enthalten. print "\012"liefert das gleiche Ergebnis wie Echo. Frage mich, warum ksh Print und kein Echo eingebaut hatte? Jedenfalls sehr interessant.

Wie viele solcher Edelsteine ​​aus ein paar Jahren warten darauf, von einem Schnitt im Jahr 2016 entdeckt zu werden? +1
iruvar

+1. Vielen Dank. Könnten Sie die Quellen (Referenzen) zum Zweck der Erstellung eines eingebauten Befehls für mein (systematisches) Lesen / Lernen angeben?
Tim

Ich möchte eine Referenz, ein Handbuch oder einen Standard finden, um systematisch zu lesen oder zu lernen. Ich habe versucht, es im bash-Referenzhandbuch und in den POSIX-Spezifikationen nachzuschlagen. Aber ich kann es nicht finden. Ich bin mir nicht sicher, ob ich sie vermisse.
Tim

@ Tim: Da diese und andere Antworten hier erklären, einige Befehle müssen in die Schale eingebaut werden oder sie können ihre Arbeit nicht tun. Alle anderen sind rein optional . Das ist im Wesentlichen das, was mein Bourne-Shell-Quelltext-Snippet oben sagt. Da das Einfügen solcher Befehle in die Shell optional ist, kann eine maßgebliche Begründung nur die Meinung eines Implementierers enthalten.
Warren Young

19

Es gibt einen dritten Grund für die Integration einiger Befehle: Sie können verwendet werden, wenn die Ausführung externer Befehle nicht möglich ist.

Manchmal ist ein System so kaputt, dass der lsBefehl nicht funktioniert. In einigen Fällen echo *funktioniert ein noch.

Ein weiteres (wichtigeres!) Beispiel ist kill: Wenn ein System keine freien PIDs mehr hat, kann es nicht ausgeführt werden /bin/kill(weil es eine PID benötigt :-), aber das eingebaute killfunktioniert.

Übrigens whichhandelt es sich um einen externen Befehl (zumindest nicht um einen internen Befehl in der Bash), sodass keine internen Befehle aufgelistet werden können. Zum Beispiel:

$ which echo
/bin/echo
$ type -a echo
echo is a shell builtin
echo is /bin/echo

Vergessen Sie nicht, dass fast alle externen ausführbaren Dateien auf Bibliotheksdateien basieren. Manchmal ereignen sich Katastrophen und diese Bibliotheken können nicht geladen werden (Hinweis: ldconfigGeben Sie NIE aus, wenn Sie nicht genau wissen, was Sie tun). Und was ist, wenn Sie Ihre / bin-Partition oder, schlimmer noch, Ihre / sbin-Partition wegpusten, aber noch eine Shell geladen haben?
LawrenceC

Wenn Ihnen die PIDs ausgehen, kann es schwierig sein, herauszufinden, welche PID Sie töten möchten. Sie können keinen psBefehl ausführen , daher müssen Sie die PIDs manuell über suchen /proc.
Kasperd

Obwohl auf (mindestens) CentOS whichist ein Bash - Alias , dass läuft alias | /usr/bin/which --read-alias ...so das externe which können Aliase identifizieren (aber noch nicht fest eingebauten Funktionen). Ich kann mich nicht entscheiden, ob ich das für brillant oder pervers halte.
Dave_Thompson_085

An dem Punkt, an dem der Befehl ls nicht mehr funktioniert, sollten Sie das Laufwerk als Slave anstatt als Boot / Master mounten und die Dateistruktur auf diese Weise korrigieren. Ich bin mir nicht sicher, wie Sie dieses Ausmaß der Systembeschädigung mit echo beheben können, es sei denn, Sie befinden sich in einer Datei, und die Behebung würde lange dauern. Zugegeben, Sie könnten ein Bash-Skript schreiben, das die Systemstruktur korrigiert.
Jonnyjandles

13

Nach dem Bash-Referenzhandbuch geht es um Bequemlichkeit.

Shells bieten auch einen kleinen Satz integrierter Befehle (Builtins), die Funktionen implementieren, die über separate Dienstprogramme nicht oder nur schwer zu erhalten sind. Cd, break, continue und exec können beispielsweise nicht außerhalb der Shell implementiert werden, da sie die Shell selbst direkt manipulieren. Die eingebauten Befehle history, getopts, kill oder pwd könnten unter anderem in separaten Dienstprogrammen implementiert werden, sind jedoch bequemer als eingebaute Befehle zu verwenden. Alle Shell-Buildins werden in den folgenden Abschnitten beschrieben.

Das Advanced Bash Scripting Guide enthält eine detailliertere Erklärung:

„Ein builtin ist ein Befehl innerhalb der Bash Werkzeugsatz enthalten sind , buchstäblich eingebaut Dies ist entweder aus Performance - Gründen -. Builtins ausführen schneller als externe Befehle, die in der Regel aus Forking benötigt 1 einen separaten Prozess - oder weil eine bestimmte builtin direkte braucht Zugriff auf die Shell-Interna. "

Beachten Sie auch, dass echoes auf einigen Systemen ein eigenständiges Dienstprogramm gibt. Folgendes habe ich auf meinem Darwin-System (MacOSX 10.5.8 - Leopard)

$ uname -a
Darwin host.foo.org 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386
$ bash --version
GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)
Copyright (C) 2005 Free Software Foundation, Inc.
$ which echo
/bin/echo

echoist auch als integrierte Version verfügbar, aber anscheinend verwenden meine Skripte / bin / echo auf meinem Mac und verwenden eine integrierte Bash-Version auf den meisten meiner Linux- und FreeBSD-Systeme. Aber das scheint keine Rolle zu spielen, da die Skripte immer noch überall gut funktionieren.


3
Wo wir gerade von Shell-Built-Ins sprechen, sollten Sie "type" anstelle von "which" verwenden.
Teddy

Vielen Dank @Teddy. Ich habe damit begonnen, wenn ich mich erinnere. Das Leben ist viel besser dank type.
Stefan Lasiewski

6

Um die Antwort von bhm zu ergänzen, nehmen wir an, Sie /binwurden versehentlich von Ihrer entfernt PATH. Sie möchten echo $PATHdas herausfinden können, oder?


2

Obwohl die meisten Shells echoheutzutage ein eingebautes enthalten , enthalten die GNU CoreUtils auch eine eigenständige Implementierung davon:

$ which echo
/bin/echo
$ dpkg -S /bin/echo
coreutils: /bin/echo

Es hört sich so an, als hätten Sie GNU Coreutils nicht installiert (die meisten Linux-basierten Desktop- und Server-Betriebssysteme haben es standardmäßig installiert, aber eingebettetes Linux oder anderes UNIX könnte stattdessen alternative Sammlungen von Shell-Dienstprogrammen verwenden).

BTW: Wenn man sich anschaut , Busybox , sehen Sie , dass ls, psund catsind auch eingebaute dort Befehle (oder zumindest sein kann, es für embeded Systeme verwendet wird und alles nicht ausgelassen werden benötigt kann).


3
Die Tests des ursprünglichen Posters stützen nicht die Hypothese, /bin/echodie nicht existiert. Sie zeigen nur, dass das eingebaute echoProgramm Vorrang vor allen Programmen im PATH hat.
Warren Young

1

Hier ist der wahre Grund, warum echoeine Shell eingebaut werden sollte:

Angenommen, Sie haben ein Passwort in $PASSWORD. Wie schreibt man es in eine Datei ./password? Natürlich würden die meisten Programmierer schreiben:

echo "$PASSWORD" >./password

Wenn echoes sich jedoch nicht um eine integrierte Shell handelt, wird das Kennwort durch psInformationen an alle Benutzer weitergegeben .

Natürlich können Sie, wenn Sie clever sein möchten, ein Kennwort speichern, ohne echoeine andere Shell-Funktion ausnutzen zu müssen:

cat >./password <<EOF
${PASSWORD}
EOF

Als echoeingebautes Kennwort ist jedoch ein wichtiger Sicherheitsgurt, da der naheliegendste Weg, ein Kennwort in einer Datei zu speichern, ebenfalls funktionieren sollte.


3
Obwohl dies ein nützlicher Nebeneffekt ist, finde ich es höchst zweifelhaft, dass dies der Grund war.
Plugwash

@ DepressedDaniel: Was unterstützt dich? Wo ist die Referenz, die Sie verwendet haben, um Ihre Antwort zu unterstützen?
Joker
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.