Grundlegendes zu Shell-Builtin-Befehlen

chevallier 05/10/2018. 2 answers, 805 views
bash shell shell-builtin

In dem Bash-Handbuch steht das geschrieben

Builtin commands are contained >>> within <<< the shell itself 

Auch diese Antwort besagt, dass

A built-in command is simply a command that the shell carries out itself,
instead of interpreting it as a request to load and run some
>>> other program <<< 

Wenn ich compgen -b auf bash 4.4 ausführe, compgen -b ich eine Liste aller Shell-Builtin-Befehle. Ich sehe zum Beispiel, dass [ und kill als Shell-Built-Ins aufgelistet sind. Aber ihre tatsächlichen Standorte sind:

/usr/bin/[
/bin/kill 

Ich dachte, dass ein builtin Befehl bedeutet, dass der Befehl in die ausführbare Datei /bin/bash kompiliert wird. Was mich wirklich verwirrt: Bitte korrigieren Sie mich, aber wie kann ein separater Befehl builtin , wenn er eigentlich nicht Teil der Shell ist?

2 Answers


Kusalananda 05/10/2018.

Die Befehle, die in die Shell eingebaut werden, sind oft eingebaut, weil die Leistung dadurch erhöht wird. Der Aufruf von external printf ist beispielsweise langsamer als der eingebaute printf .

Da einige Dienstprogramme nicht eingebaut werden need , werden sie auch als external Dienstprogramme zur Verfügung gestellt, sofern sie nicht speziell sind. Auf diese Weise werden Skripts nicht beschädigt, wenn sie von einer Shell interpretiert werden, die keine integrierte Entsprechung bereitstellt.

Einige Shell-Einbauten bieten auch Erweiterungen für den externen äquivalenten Befehl. Bash's printf ist zum Beispiel in der Lage zu tun

$ printf -v message 'Hello %s' "world"
$ echo "$message"
Hello world 

(auf eine Variable drucken), was das externe /usr/bin/printf einfach nicht kann, da es keinen Zugriff auf die Shell-Variablen in der aktuellen Shell-Sitzung hat (und sie nicht ändern kann).

Eingebaute Dienstprogramme haben auch not die Einschränkung, dass ihre erweiterte Befehlszeile kürzer als eine bestimmte Länge sein muss. Tun

printf '%s\n' * 

ist daher sicher, wenn printf ein Shell-eingebauter Befehl ist. Die Beschränkung der Länge der Befehlszeile stammt von der C-Bibliotheksfunktion execve() die zum Ausführen eines externen Befehls verwendet wird. Wenn die Befehlszeile und die aktuelle Umgebung größer als ARG_MAX Bytes sind (siehe getconf ARG_MAX in der Shell), getconf ARG_MAX der Aufruf von execve() fehl. Wenn das Dienstprogramm in die Shell integriert ist, muss execve() nicht aufgerufen werden.

Eingebaute Dienstprogramme haben Vorrang vor Dienstprogrammen, die in $PATH . Um einen eingebauten Befehl in bash zu deaktivieren, benutzen Sie zB

enable -n printf 

Es gibt eine kurze Liste von Dienstprogrammen, die in eine Shell eingebaut werden müssen (aus der POSIX-Standardliste mit speziellen integrierten Funktionen ).

break
colon (:)
continue
dot (.)
eval
exec
exit
export
readonly
return
set
shift
times
trap
unset 

Diese müssen eingebaut sein, da sie direkt die Umgebung und den Programmfluss der aktuellen Shell-Sitzung manipulieren. Ein externes Dienstprogramm wäre dazu nicht in der Lage.

Interessanterweise ist cd nicht Teil dieser Liste, aber POSIX sagt folgendes :

Da sich cd auf die aktuelle Shell-Ausführungsumgebung auswirkt, wird sie immer als reguläre Shell bereitgestellt. Wenn es in einer Subshell- oder separaten Umgebung zur Ausführung von Dienstprogrammen aufgerufen wird, z.

(cd /tmp)
nohup cd
find . -exec cd {} \; 

Es wirkt sich nicht auf das Arbeitsverzeichnis der Umgebung des Aufrufers aus.

Ich gehe daher davon aus, dass die "speziellen" Built-Ins keine externen Gegenstücke haben können, während cd in der Theorie haben könnte (aber es würde nicht viel tun).


terdon 05/10/2018.

Sie werden (sehr verständlicherweise) durch die Tatsache verwirrt, dass einige Builtins both als eingebaute and als externe Befehle existieren. So, während Sie richtig sind, dass zum Beispiel ein /bin/[ Befehl, bedeutet dies nicht, dass seine "tatsächlichen Ort" ist in /bin .

Eine einfache Möglichkeit, dies zu testen, besteht darin, den type mit dem Schalter -a auszuführen, der alle verfügbaren Instanzen eines Befehls anzeigt. Auf meinem Arch-System zeigt das:

$ type -a [
[ is a shell builtin
[ is /sbin/[
[ is /usr/sbin/[
[ is /usr/bin/[ 

Beachten Sie, dass /sbin , /usr/sbin und /bin Symlinks sind, die auf /usr/bin verweisen, also gibt es nur einen externen [ :

$ readlink -f /usr/sbin /sbin /bin/
/usr/bin
/usr/bin
/usr/bin 

Wie Sie sehen können, ist [ sowohl ein eingebauter als auch ein externer Befehl, und dasselbe gilt für verschiedene andere Shell-Builtins. Das ändert jedoch nichts daran, dass sie auch Shell-Built-Ins sind, die in die Shell selbst kompiliert sind.

Related questions

Hot questions

Language

Popular Tags