Pourquoi echo est-il un shell construit dans la commande?

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

Pourquoi ne pas l' écho d' un utilitaire indépendant comme ls, ps, catetc? Pourquoi est-ce spécifique à la coquille? Des bonnes raisons?

Lazer
la source
5
Gardez à l'esprit que cela est spécifique à la coquille. ZSH le construit, pas BASH.
tsvallender
21
@tsv: le echoplus certainement est un Bash intégré. En fait, il est intégré à toutes les grandes coques modernes.
pause jusqu'à nouvel ordre.

Réponses:

71

Il y a deux classes de commandes intégrées:

  1. Certaines commandes doivent être intégrées au programme shell lui-même car elles ne peuvent pas fonctionner si elles sont externes.

    cdIl en est un puisque, s'il était externe, il ne pourrait changer que de son propre répertoire. cela ne pourrait pas affecter le répertoire de travail actuel du shell. (Voir aussi: Pourquoi n'est cdpas un programme? )

  2. L'autre classe de commandes est intégrée au shell uniquement pour des raisons d'efficacité.

    La page de manuel a une section sur builtins qui mentionne , et comme exemples de commandes dans cette classe.dash printfechotest

Les systèmes Unix ont toujours inclus des exécutables distincts pour les commandes de cette seconde classe. Ces exécutables distincts sont toujours disponibles sur tous les systèmes Unixy que j'ai utilisés, même s'ils sont également intégrés à chaque shell que vous êtes susceptible d'utiliser. ( POSIX exige en fait que ces exécutables soient présents.)

Je crois avoir echoété intégré à la coquille dans AT & T Unix System V version 3.1. Je me base sur des comparaisons de deux éditions différentes de manuels pour les systèmes Unix de la série AT & Ts 3B1 . Quelqu'un a gracieusement numérisé les éditions de 1986 de ces manuels et les a mis en ligne ; ceux-ci correspondent à la version originale de SVR3. Vous pouvez voir que cela echone figure pas dans la liste à la page 523 du Manuel de l'utilisateur d' UNIX System V, volume II , à laquelle vous vous attendriez si la commande était intégrée au shell. Dans mon journal local copie des manuels de SVR3.1 de 1987, echo est répertorié dans cette section du manuel.

Je suis à peu près sûr que ce n'est pas une innovation CSRG de Berkeley qu'AT & T a rapportée à la maison. 4.3BSD est sorti la même année que SVR3, 1986, mais si vous consultez la page de manuel sh.1 de 4.3BSD , vous voyez que cela echone figure pas dans la liste des commandes intégrées de la section "Commandes spéciales". Si CSRG agissait ainsi, cela nous laisserait vouloir une source documentée pour le prouver.

À ce stade, vous vous demandez peut-être si echole shell avait été construit avant SVR3.1 et si ce fait n’avait tout simplement pas été documenté jusque-là. Le dernier code source AT & T Unix pré-SVR3 dont je dispose se trouve dans l’ archive PDP-11 System III , dans laquelle vous trouverez le code source du shell Bourne. Vous ne trouverez pas echodans la table de commande intégrée, qui se trouve dans /usr/src/cmd/sh/msg.c. D'après les horodatages de ce fichier, cela prouve que ce echon'était certainement pas dans la coquille en 1980.


Trivia

Le même répertoire contient également un fichier appelé builtin.cqui ne contient rien sur cette question, mais nous trouvons ce commentaire intéressant:

/*      
    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..
*/      
Warren Young
la source
À la page 385 du MU UM, volume II de SysV que vous avez mentionné, il y a la printcommande intégrée de ksh qui est supposée se comporter comme suit echo. Cette commande est présente dans quelque chose comme AT & T Unix SVR4 2.1 i386 d’ISC. print "\012"donne le même résultat que l'écho. Je me demande pourquoi ksh avait une impression et non un écho intégré? En tout cas vraiment intéressant.
Combien de ces joyaux d'il y a quelques années sont pris au piège en attendant d'être découverts par un montage en 2016? +1
iruvar
+1 Merci. Pourriez-vous fournir les sources (références) dans le but de créer une commande intégrée, pour ma lecture / apprentissage (systématique)?
Tim
Je veux trouver une référence, un manuel ou une norme à lire ou à apprendre systématiquement. J'ai essayé de le rechercher dans le manuel de référence bash et les spécifications POSIX. Mais je ne le trouve pas. Je ne suis pas sûr s'ils me manquent.
Tim
@ Tim: Comme cela et d'autres réponses ici expliquent, certaines commandes doivent être intégrées dans le shell ou elles ne peuvent pas faire leur travail. Tous les autres sont purement optionnels . C'est essentiellement ce que mon extrait de source de shell Bourne dit ci-dessus, en fait. Comme la construction de telles commandes dans le shell est facultative, une justification faisant autorité ne peut donner que l’opinion d’un réalisateur.
Warren Young
19

Il y a une troisième raison pour laquelle certaines commandes sont intégrées: elles peuvent être utilisées lorsque l'exécution de commandes externes est impossible.

Parfois, un système devient tellement endommagé que la lscommande ne fonctionne pas. Dans certains cas, un echo *fonctionnera toujours.

Un autre exemple (plus important!) Est le suivant kill: si un système manque de PID gratuits, il n’est pas possible de s’exécuter /bin/kill(car il nécessite un PID :-), mais l’intégration killfonctionnera.

Btw., whichEst une commande externe (du moins elle n'est pas interne dans bash), elle ne peut donc pas lister les commandes internes. Par exemple:

$ which echo
/bin/echo
$ type -a echo
echo is a shell builtin
echo is /bin/echo
bhm
la source
N'oubliez pas que presque tous les exécutables externes reposent sur des fichiers de bibliothèque. Parfois, des catastrophes surviennent et ces bibliothèques ne peuvent pas être chargées (conseil: N'émettez JAMAIS ldconfigsi vous ne savez PAS exactement ce que vous faites). De plus, que se passe-t-il si vous supprimez votre partition / bin, ou pire, votre partition / sbin, tout en gardant un shell chargé?
LawrenceC
Si vous manquez de PID, il peut être difficile de savoir quel PID vous souhaitez tuer. Vous ne pouvez pas exécuter de pscommande, vous devez donc rechercher les PID manuellement /proc.
Kasperd
Bien que sur (au moins) CentOS whichsoit un alias bash qui s'exécute de alias | /usr/bin/which --read-alias ...sorte que l'externe which puisse identifier des alias (mais pas encore intégrés). Je ne peux pas décider s'il faut considérer cela comme brillant ou pervers.
dave_thompson_085
Au moment où la commande ls ne fonctionne plus, je pense que vous devriez monter le lecteur en tant qu'esclave au lieu de boot / master et corriger la structure de fichier de cette façon. Je ne sais pas comment vous pourriez réparer cette corruption de système avec écho, sauf si vous faites écho dans un fichier et que cela prendrait beaucoup de temps à réparer. Cela dit, vous pouvez écrire un script bash destiné à corriger la structure du système.
jonnyjandles
13

Selon le manuel de référence de Bash , il s'agit de commodité.

Les shells fournissent également un petit ensemble de commandes intégrées implémentant des fonctionnalités impossibles ou peu pratiques à obtenir via des utilitaires distincts. Par exemple, cd, break, continue et exec) ne peuvent pas être implémentés en dehors du shell car ils manipulent directement le shell lui-même. Les commandes intégrées history, getopts, kill ou pwd, entre autres, peuvent être implémentées dans des utilitaires distincts, mais leur utilisation est plus pratique comme commandes intégrées. Toutes les fonctions intégrées du shell sont décrites dans les sections suivantes.

Le Guide de script avancé Bash contient une explication plus détaillée:

"Une commande intégrée est une commande contenue dans le jeu d’outils Bash, littéralement intégrée. C’est soit pour des raisons de performance: les fonctions intégrées s'exécutent plus rapidement que les commandes externes, qui nécessitent généralement l’interrogation 1 d’ un processus distinct - accès aux internes du shell ".

Notez également qu'il echoexiste un utilitaire autonome sur certains systèmes. Voici ce que j'ai sur mon système Darwin (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

echoest également disponible en version intégrée, mais apparemment, mes scripts utilisent / bin / echo sur mon Mac et utilisent une interface intégrée Bash sur la plupart de mes systèmes Linux et FreeBSD. Mais cela ne semble pas avoir d’importance, car les scripts fonctionnent toujours partout.

Stefan Lasiewski
la source
3
En parlant de shell intégré, vous devriez utiliser "type" au lieu de "quel".
Teddy
Merci @ Teddy. J'ai commencé à faire ça, quand je m'en souviens. La vie est bien meilleure grâce à type.
Stefan Lasiewski
6

Pour compléter la réponse de bhm, disons que /binvous avez accidentellement été retiré de votre fichier PATH. Vous voulez pouvoir le echo $PATHsavoir, non?

Daniel Hershcovich
la source
2

Bien que la plupart des shells intègrent de echonos jours, GNU CoreUtils en inclut également une implémentation autonome:

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

Il semble que GNU Coreutils ne soit pas installé (la plupart des systèmes d’exploitation de serveur et de bureau basés sur Linux le sont installés par défaut, mais Linux ou un autre système UNIX intégré pourrait utiliser des collections alternatives d’utilitaires shell).

BTW: si vous regardez Busybox , vous verrez cela ls, pset ce catsont aussi des commandes intégrées (ou du moins peuvent l'être; il est utilisé pour les systèmes intégrés et tout ce qui n'est pas nécessaire peut être omis).

JanC
la source
3
Les tests de l'affiche originale ne corroborent pas l'hypothèse qui /bin/echon'existe pas. Ils montrent simplement que la commande intégrée prime sur tout echoprogramme de PATH.
Warren Young
1

Voici la vraie raison pour laquelle echoun shell devrait être intégré:

Supposons que vous ayez un mot de passe dans $PASSWORD. Comment écrivez-vous dans un fichier ./password? Naturellement, la plupart des programmeurs écriraient:

echo "$PASSWORD" >./password

Cependant, s'il echon'y avait pas de shell intégré, le mot de passe serait transmis à tous les utilisateurs par le biais d' psinformations.

Bien sûr, si vous voulez être intelligent à ce sujet, vous pouvez trouver un moyen de stocker un mot de passe sans echo, peut-être en exploitant une autre fonctionnalité du shell:

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

Cependant, la echoceinture de sécurité est un élément important car le moyen le plus évident de sauvegarder un mot de passe dans un fichier devrait également fonctionner.

DepressedDaniel
la source
3
Bien que ce soit un effet secondaire utile, j’ai le plus grand doute que c’était la raison.
plugwash
@ DepressedDaniel: Qu'est-ce qui vous soutient? Où est la référence que vous avez utilisée pour appuyer votre réponse?
Joker