Le but de cette question est de répondre à une curiosité et non de résoudre un problème informatique particulier. La question qui se pose est la suivante: pourquoi les utilitaires POSIX obligatoires ne sont-ils généralement pas intégrés aux implémentations de shell?
Par exemple, j’ai un script qui lit en principe quelques petits fichiers texte et vérifie qu’ils sont correctement formatés, mais il faut 27 secondes pour s’exécuter, sur ma machine, en raison d’un nombre considérable de manipulations de chaînes. Cette manipulation de chaîne crée des milliers de nouveaux processus en appelant divers utilitaires, d’où la lenteur. Je suis assez confiant que si certains des services publics ont été intégrés, à savoir grep
, sed
, cut
, tr
et expr
, le script courrait dans une seconde ou moins ( d' après mon expérience en C).
Il semble que dans de nombreux cas, la construction de ces utilitaires puisse faire la différence entre une solution dans un script shell et des performances acceptables.
De toute évidence, il y a une raison pour laquelle il a été choisi de ne pas intégrer ces utilitaires. Peut-être qu'avoir une version d'un utilitaire au niveau du système évite que plusieurs versions inégales de cet utilitaire soient utilisées par différents shells. Je ne peux vraiment pas penser à de nombreuses autres raisons de garder la surcharge de créer autant de nouveaux processus, et POSIX définit suffisamment les utilitaires pour qu'il ne semble pas être un problème d'avoir différentes implémentations, tant qu'ils sont tous POSIX conforme. Du moins pas un problème aussi important que l'inefficacité d'avoir autant de processus.
printf
, etc.) ont été incorporés dans des coquilles lorsqu'elles ont été jugées suffisamment utiles.awk
est un utilitaire obligatoire POSIX, et convient particulièrement bien (qui est, très rapide) pour mettre en œuvre des scripts que vous pourriez mettre en œuvre en utilisant autrementsed
,cut
,tr
,grep
etexpr
dans un script shell.Réponses:
Les scripts shell ne doivent pas s'exécuter avec ce type de vitesse. Si vous voulez améliorer la vitesse de votre script, essayez-le en Perl. Si cela est toujours trop lent, vous devrez alors passer à un langage statiquement typé tel que java ou c, ou écrire un module C pour perl qui exécute les parties trop lentes.
Shell est le premier niveau de prototypage, si vous pouvez prouver le concept avec shell, puis passez à un meilleur langage de script qui peut faire plus de vérifications en vérifiant que cela prendrait des acres de shell.
Un système d'exploitation Unix devrait inclure de nombreux petits programmes qui effectuent des tâches bien définies qui constituent une image plus grande. C’est une bonne chose car cela compartimente les plus gros programmes. Jetez un coup d'œil à qmail, par exemple, et comparez-le à sendmail. qmail est composé de nombreux programmes:
http://www.nrg4u.com/qmail/the-big-qmail-picture-103-p1.gif
L'exploitation du démon réseau ne vous aiderait pas à exploiter le gestionnaire de files d'attente.
la source
cd
oupwd
.cd
est intégré - et il doit l'être, car la modification du répertoire de travail dans un sous-processus n'affecte pas les processus parents.Pour être conforme à POSIX, un système 1 est requis pour fournir la plupart des utilitaires sous forme de commandes autonomes.
Leur intégration impliquerait qu'ils doivent exister dans deux endroits différents, à l'intérieur et à l'extérieur du shell. Bien sûr, il serait possible d'implémenter la version externe en utilisant un encapsuleur de script shell à la commande intégrée, mais cela désavantagerait les applications non-shell appelant les utilitaires.
Notez que BusyBox a emprunté le chemin que vous avez suggéré en implémentant de nombreuses commandes en interne et en fournissant la variante autonome en utilisant des liens vers elle-même. L'un des problèmes est que, si le jeu de commandes peut être assez volumineux, les implémentations sont souvent un sous-ensemble de la norme et ne sont donc pas conformes.
Notez également qu’au moins
ksh93
,bash
etzsh
allez plus loin en fournissant des méthodes personnalisées pour que le shell en cours d’exécution charge dynamiquement les commandes intégrées à partir de bibliothèques partagées. Techniquement, rien n'empêche alors tous les utilitaires POSIX d'être implémentés et rendus disponibles en tant que fonctions intégrées.Enfin, la création de nouveaux processus est devenue une opération assez rapide avec les systèmes d’exploitation modernes. Si vous rencontrez un problème de performances, des améliorations pourraient être apportées pour accélérer l'exécution de vos scripts.
1 POSIX.1-2008
la source
fork
non suivi deexec
;fork
est de nos jours une opération très légère comparée àexec
.nofork
intégrées de busybox comme ayant environ 10 fois moins de temps système que les commandesnoexec
intégrées, qui à leur tour avaient environ 5 fois moins de temps système que fork + exec d'un fichier binaire séparé. Définitions selon unix.stackexchange.com/a/274322/29483 Il est intéressant de noter que busybox ne fait pasnofork
tout, bien que je sache que le code de busybox est raccourci en ne nettoyant pas la mémoire et qu'il repose simplement sur un processus éphémère.À partir du manuel de référence BASH ,
Comme vous le savez sans doute, la philosophie UNIX repose sur de nombreuses applications aux fonctionnalités limitées. Chaque élément intégré a une très bonne raison pour laquelle il est intégré. Tout le reste ne l'est pas. Je pense qu'une catégorie de questions plus intéressante va dans le sens de, "pourquoi est
pwd
-ce exactement intégré?"la source
cd
serait un meilleur exemple de ce qui est impossible à mettre en œuvre séparément.cd
doit être intégré,pwd
ne le fait pas. Alors pourquoi lesbash
développeurs ont-ils choisi de l'inclure?/bin/bash
existe, mais c'est toujours intégré. Voir la liste des éléments intégrés sur gnu.org/software/bash/manual/html_node/…Les gars d'AT & T se sont demandé la même chose
Si vous examinez l'historique de la boîte à outils AT & T Software (actuellement en attente sur github depuis le départ de l'équipe principale), c'est exactement ce qu'ils ont fait avec le shell AT & T Korn, alias ksh93.
Les performances ont toujours été une partie de la motivation des responsables de ksh93, et lors de la construction de ksh, vous pouvez choisir de construire de nombreux utilitaires POSIX courants sous forme de bibliothèques à chargement dynamique. En liant ces commandes à un nom de répertoire comme
/opt/ast/bin
, vous pouvez contrôler la version de la commande à utiliser, en fonction de la position de ce nom de répertoire dans$PATH
.Exemples:
La liste complète se trouve dans le répertoire github ast .
Notez que la plupart des outils ast ont leur propre provenance et différeraient fortement des implémentations plus courantes de gnu. L'équipe de recherche d'AT & T s'est conformée aux normes officielles, ce qui était le moyen de parvenir à l'interopérabilité lorsqu'il était impossible de partager le code.
la source
Nous n'avons donc pas mobilisé les ressources pour optimiser l'outil d'origine, afin de répondre à tous les souhaits. Je suppose que ce qu’il faut expliquer, c’est combien ce désir spécifique aurait un coût de mise en œuvre.
c'est une mauvaise hypothèse :-P.
Les systèmes post-POSIX continuent de devenir plus puissants et plus pratiques pour de bonnes raisons; En tant que norme après coup, elle ne rattrape jamais réellement.
Ubuntu a commencé à essayer de passer à un shell POSIX dépouillé pour les scripts, afin d'optimiser l'ancien processus d'initialisation de System V. Je ne dis pas qu'il a échoué, mais il a fait déclencher de nombreux bugs qui ont dû être nettoyé: « bashismes », les scripts qui ont paru sous
/bin/sh
tout en supposant que lesbash
caractéristiques étaient disponibles.POSIX sh n’est pas un bon langage de programmation généraliste. Son objectif principal est de fonctionner correctement en tant que shell interactif. Dès que vous commencez à enregistrer vos commandes dans un script, sachez que vous vous approchez d'un tarpit Turing . Par exemple, il est impossible de détecter des défaillances au milieu d'un pipeline normal .
bash
ajoutéset -o pipefail
pour cela, mais ce n'est pas dans POSIX.Des fonctionnalités similaires, utiles mais non standardisées, sont fournies par presque tous les utilitaires plus complexes que
true
.Pour la classe de tâches que vous décrivez, vous pouvez tracer une ligne approximative entre Awk, Perl et, de nos jours, Python. Différents outils ont été créés et ont évolué indépendamment. Vous attendriez-vous par exemple à ce que GNU Awk soit intégré à un libutilposixextended?
Je ne dis pas que nous avons maintenant une approche universellement meilleure que je peux vous indiquer. J'ai un faible pour Python. Awk est étonnamment puissant, même si certaines fonctionnalités spécifiques à GNU Awk m'ont frustré. Mais le fait est que le traitement d'un grand nombre de chaînes individuellement (probablement à partir de lignes de fichiers) n'était pas un objectif de conception du shell POSIX.
la source
cat -@fnord foo
le shell devrait décider de ne pas définir le-@
moyen nécessaire pour appeler la commande réelle, maiscat <foo >bar
le shell ne devrait pas avoir besoin de générer un autre processus.Il y a aussi la question de: dans quel shell voulez-vous le construire?
La plupart des systèmes Unix / Linux ont plusieurs shells différents qui sont développés indépendamment (sh / bash / korn / ???). Si vous construisez les outils dans le shell, vous obtiendrez une implémentation différente de ces outils pour chaque shell. Cela entraînerait une surcharge, et vous pourriez vous retrouver avec différentes fonctionnalités / bogues dans, par exemple, grep, selon le shell que vous utilisiez pour l'appeler.
la source
Beaucoup ont bien répondu. Je compte seulement complimenter ces réponses. Je pense que la philosophie UNIX est qu’un outil doit faire une chose et le faire bien. Si l’on essaie de créer un outil complet, c’est beaucoup plus d’échecs. Limiter la fonctionnalité de cette manière rend un jeu d’outils fiable.
En outre, considérez que si des fonctionnalités telles que sed ou grep étaient intégrées au shell, serait-il aussi facile d'appeler à partir de la ligne de commande quand vous le souhaiteriez?
En terminant, considérons que certaines des fonctionnalités que vous souhaitez intégrer à BASH se trouvent dans BASH . Par exemple, la possibilité de correspondance RE dans BASH est implémentée à l'aide de l' opérateur binaire = ~ (voir Shell Grammar dans la page Manual pour plus d'informations, reportez-vous à la discussion de la construction [[]] pour if ). Comme exemple très rapide, disons que je cherche un fichier avec 2 chiffres hexadécimaux:
En ce qui concerne les fonctionnalités de type sed , consultez la rubrique Extension de paramètre dans l' en -tête Expansion de la même page de manuel. Vous verrez une multitude de choses que vous pouvez faire qui rappellent sed. J'utilise le plus souvent sed pour effectuer un changement de type de substitution en texte. S'appuyant sur ce qui précède:
En fin de compte, est-ce que ce qui précède est "meilleur" que?
la source
C'est, je suppose, un accident historique.
Lorsque UNIX a été créé à la fin des années 1960 et au début des années 1970, les ordinateurs n’avaient pas autant de mémoire qu’aujourd’hui. À l'époque, il aurait été possible d'implémenter toutes ces fonctionnalités en tant que commandes intégrées au shell, mais en raison de limitations de mémoire, il leur aurait fallu limiter la quantité de fonctionnalités qu'elles pourraient implémenter, ou risquer de manquer de mémoire et / ou de supprimer la corbeille d'échange. problèmes.
D'autre part, en implémentant la fonctionnalité donnée en tant que programmes distincts et en rendant les deux appels système requis pour démarrer un nouveau processus aussi léger que possible, ils pourraient créer un environnement de script qui ne présente pas ces problèmes et qui fonctionne toujours à un rythme raisonnable. la vitesse.
Bien sûr, une fois que ces éléments sont mis en œuvre en tant que processus distincts, les utilisateurs les lancent à partir de programmes qui ne sont pas des shells. Ils doivent ensuite rester comme ça ou tout à coup, tout ce logiciel commence à casser.
Cela ne veut pas dire que vous ne pouvez pas implémenter certaines fonctionnalités à deux reprises, et en fait, certains shells implémentent des fonctionnalités qui sont supposées être un programme externe intégré à un shell; par exemple, bash implémente la
echo
commande en tant que fonction intégrée, mais il y a aussi un/usr/bin/echo
la source