J'ai essayé which cd
et il n'a pas donné de chemin mais a renvoyé le code de sortie 1 (vérifié avec echo $?
). Le coreutil cd
lui-même fonctionne, donc l'exécutable devrait être là, non? J'ai également exécuté un find
for cd
, mais aucun fichier exécutable n'a été affiché. Comment est-il alors mis en œuvre?
Mise à jour:
Je ne sais pas si je devrais poser cette question dans un autre article mais comme je pense que c'est bien ici, j'étends (?) L'article ... Donc la réponse était en fait assez simple, il n'y a pas d'exécutable pour ça - parce que c'est un module intégré - Mais j'ai trouvé que certains modules intégrés (shell bash dans Fedora) ont les fichiers exécutables! Donc intégré -> aucun exécutable n'est pas vrai, je suppose? Peut-être une réponse expliquant ce que sont les commandes intégrées (commandes intégrées?), Ce qui est en fait le problème ici, plutôt que de se concentrer davantage sur cd
... Certains bons liens publiés précédemment indiquent que les commandes intégrées ne sont pas des programmes ... alors qu'est-ce que c'est? Comment travaillent-ils? S'agit-il simplement de fonctions ou de threads du shell?
la source
type
commandecd
doit être un programme intégré: pourquoi le cd n'est-il pas un programme? et celui-ci sur pourquoitype
vaut mieux quewhich
: Pourquoi ne pas utiliser "qui"? Que faut-il utiliser alors?Réponses:
La commande
cd
ne peut pas être un exécutableDans un shell,
cd
est utilisé pour "aller dans un autre répertoire", ou plus formellement, pour changer le répertoire de travail courant (CWD). Il est impossible de l'implémenter en tant que commande externe:Le répertoire appartient à un processus
Le répertoire de travail actuel est le répertoire utilisé pour interpréter les chemins relatifs afin d'obtenir un chemin complet pouvant être utilisé pour accéder aux fichiers. Les chemins relatifs sont utilisés à de nombreux endroits et l'interprétation dans un processus ne doit pas influencer un autre processus.
Pour cette raison, chaque processus a son propre répertoire de travail actuel.
cd
consiste à changer le répertoire de travail actuel du processus shell, par exemplebash
.S'il s'agissait d'une commande externe, un exécutable dans le chemin, exécutant cet exécutable créerait un processus avec son propre répertoire de travail, sans influencer celui du shell actuel. Même si la commande externe change son répertoire, ce changement disparaît lorsque le processus externe se termine.
Commandes intégrées au shell
Il est donc inutile d'exécuter une commande externe pour la tâche de
cd
. La commandecd
doit appliquer une modification au processus shell en cours d'exécution.Pour ce faire, il s'agit d'une «commande intégrée» du shell.
Les commandes intégrées sont des commandes qui se comportent de manière similaire aux commandes externes, mais sont implémentées dans le shell (ne font donc
cd
pas partie des coreutils). Cela permet à la commande de changer l'état du shell lui-même, dans ce cas d'appelerchdir()
see (voirman 2 chdir
);Sur
which
Maintenant, la réponse à la question du titre est simple:
la commande exécutable
which
ne peut pas nous dire que cd est une commande intégrée car une commande exécutable ne sait rien des commandes intégrées.Alternative
type -a
Comme alternative à
which
, vous pouvez utilisertype -a
; Il peut voir les commandes et les commandes exécutables; De plus, il voit des alias et des fonctions - également implémentés dans le shell:la source
cd
un shell est intégré.cd
est un shell shell mandaté par POSIX:Bien que cela ne dise pas explicitement qu'il doit être intégré, la spécification continue dans la description de
cd
:Du
bash
manuel :Je suppose que vous pourriez penser à une architecture qui
cd
ne doit pas nécessairement être intégrée. Cependant, vous devez voir ce qu'implique un intégré. Si vous écrivez du code spécial dans le shell pour faire quelque chose pour une commande quelconque, vous vous approchez d'avoir une fonction intégrée. Plus vous en faites, mieux c'est d'avoir simplement un intégré.Par exemple, vous pouvez demander au shell d'avoir IPC pour communiquer avec les sous-processus, et il y aurait un
cd
programme qui vérifierait l'existence du répertoire et si vous avez l'autorisation d'y accéder, puis communique avec le shell pour lui dire de changer son annuaire. Cependant, vous devrez ensuite vérifier si le processus de communication avec vous est un enfant (ou créer des moyens de communication spéciaux avec les enfants uniquement, tels qu'un descripteur de fichier spécial, une mémoire partagée, etc.) et si le processus est en fait exécuter lecd
programme de confiance ou autre chose. C'est toute une boîte de vers.Ou vous pourriez avoir un
cd
programme qui fait l'chdir
appel système, et le démarre un nouveau shell avec toutes les variables d'environnement actuelles appliquées au nouveau shell, puis tue son shell parent (en quelque sorte) une fois terminé. 1Pire, vous pourriez même avoir un système où un processus peut modifier les environnements d'autres processus (je pense que techniquement, vous pouvez le faire avec des débogueurs). Cependant, un tel système serait très, très vulnérable.
Vous vous retrouverez à ajouter de plus en plus de code pour sécuriser ces méthodes, et il est considérablement plus simple d'en faire simplement un intégré.
Que quelque chose soit un exécutable ne l'empêche pas d'être intégré. Exemple:
echo
ettest
echo
ettest
sont des utilitaires mandatés par POSIX (/bin/echo
et/bin/test
). Pourtant, presque tous les shell populaires ont un intégréecho
ettest
. De même,kill
est également intégré qui est disponible en tant que programme. Parmi les autres:sleep
(pas aussi commun)time
false
true
printf
Cependant, il existe certains cas où une commande ne peut pas être autre chose qu'une fonction intégrée. L'un d'eux est
cd
. En règle générale, si le chemin d'accès complet n'est pas spécifié et que le nom de la commande correspond à celui d'un code intégré, une fonction adaptée à cette commande est appelée. Selon le shell, le comportement du builtin et celui de l'exécutable peuvent différer (c'est particulièrement un problème pourecho
, qui a des comportements très différents . Si vous voulez être certain du comportement, il est préférable d'appeler l'exécutable en utilisant le chemin complet et définissez des variables commePOSIXLY_CORRECT
(même alors, il n'y a pas de réelle garantie).Techniquement, rien ne vous empêche de fournir un système d'exploitation qui est également un shell et a toutes les commandes en tant que intégré. Près de cette extrémité extrême se trouve la BusyBox monolithique . BusyBox est un binaire unique qui (selon le nom avec lequel il est appelé) peut se comporter comme n'importe lequel des 240 programmes , y compris un shell Almquist (
ash
). Si vous désactivezPATH
pendant l'exécution de BusyBoxash
, les programmes disponibles dans BusyBox sont toujours accessibles sans spécifier aPATH
. Ils se rapprochent d'être des commandes intégrées au shell, sauf que le shell lui-même est une sorte de commande intégrée à BusyBox.Étude de cas: le shell Debian Almquist (
dash
)Si vous regardez la
dash
source, le thread d'exécution est quelque chose comme ça (bien sûr, avec des fonctions supplémentaires impliquées lorsque des tuyaux et d'autres choses sont utilisées):main
→cmdloop
→evaltree
→evalcommand
evalcommand
utilise ensuitefindcommand
pour déterminer la commande. S'il s'agit d'une fonction intégrée, alors :cmdentry.u.cmd
est unstruct
(struct builtincmd
), dont un des membres est un pointeur de fonction avec une signature typique demain
:(int, char **)
. Laevalbltin
fonction appelle (selon que laeval
commande intégrée est la commande ou non)evalcmd
ou ce pointeur de fonction. Les fonctions réelles sont définies dans divers fichiers source.echo
, par exemple, c'est :Tous les liens vers le code source dans cette section sont basés sur un numéro de ligne, ils peuvent donc changer sans préavis.
1 Les systèmes POSIX ont un
cd
exécutable .Note latérale:
Il y a beaucoup d'excellents articles sur Unix et Linux qui traitent du comportement du shell. En particulier:
cd
commande externe?la source
cd
texte d'aide avechelp cd
(la même chose pour toutes les commandes intégrées au shell)help
c'est un bash intégré (pour zsh, c'estrun-help cd
)cd
doit être comme un shell intégré ... mais basé sur la façon dont les propriétés de processus et leur transfert fonctionnent sous UNIXcd
comme un shell intégré est la seule implémentation simple. Voir la réponse de Volker Siegel .Vous ne pouvez pas trouver d'exécutable
cd
car il n'y en a pas.cd
est une commande interne de votre shell (par exemplebash
).la source
de
man which
:Comme nous pouvons le voir dans la description de
which
, il s'agit uniquement de vérifierPATH
. Donc, si vous en avez implémentébash function
, cela ne vous montrera rien. Il est préférable d'utiliser latype
commande avecwhich
.Par exemple, dans la
ls
commande Ubuntu alias pourls --color=auto
.Et si vous implémentez la fonction de test
hello
:which
ne montre rien. Maistype
:Dans ton cas:
Cela signifie que
cd
c'est un shell intégré , il est à l'intérieurbash
. Toutes les commandes bash décrites dansman bash
, dans la section COMMANDES DE CONSTRUCTION DE SHELLla source
manwhich
.which
, utilisertype
.