Comment Bash obtient-il la sortie d'un programme exécuté?

Quand j'exécute un programme dans Bash , par exemple, [ls][2] , il envoie sa sortie à la sortie standard ( fd &1 ). Et la sortie du programme exécuté est affichée dans le terminal. Comment Bash / terminal obtient-il la sortie de la command ls ?

En tant que process enfant du shell, ls hérite des descripteurs de files ouverts du shell. Et les descripteurs de file standard (stdin, stdout, stderr (ou 0, 1, 2)) sont connectés à un pseudo-terminal, géré par l'émulateur de terminal.

Par exemple (sur un système Linux):

 $ ls /proc/$$/fd -l total 0 lrwx------ 1 muru muru 64 Dec 10 16:15 0 -> /dev/pts/3 lrwx------ 1 muru muru 64 Dec 10 16:15 1 -> /dev/pts/3 lrwx------ 1 muru muru 64 Dec 10 16:15 2 -> /dev/pts/3 lrwx------ 1 muru muru 64 Dec 10 16:15 255 -> /dev/pts/3 $ ls /proc/$(pgrep terminator -f)/fd -l | grep pts/3 lrwx------ 1 muru muru 64 Dec 10 16:15 26 -> /dev/pts/3 

C'est-à-dire que la sortie de ls ou du shell lui-même n'est pas prise en charge par le shell, mais par l'émulateur de terminal (terminal GNOME, terminateur, xterm, etc.).


Vous pouvez tester ceci:

Sur Linux, trouvez un pseudoterminal ( pts ) utilisé par votre émulateur de terminal (par exemple le terminal GNOME):

 $ ls -l /proc/$(pgrep -n gnome-terminal)/fd | grep pts lrwx------ 1 muru muru 64 Dec 10 18:00 1 -> /dev/pts/1 lrwx------ 1 muru muru 64 Dec 10 18:00 15 -> /dev/pts/20 lrwx------ 1 muru muru 64 Dec 10 18:00 2 -> /dev/pts/1 

Désormais, les fds non standard (ceux autres que 0,1,2) de gnome-terminal seraient utilisés pour fournir des inputs et des sorties pour un shell. L'émulateur de terminal lit dans datatables envoyées à ce PTS et (après un certain traitement, pour les colors et autres) le présente à l'écran. Dans ce cas, ce serait 15 , connecté à pts/20 . Si j'écris quelque chose à ces points, je peux m'attendre à ce qu'il apparaisse dans ce terminal:

entrer la description de l'image ici

Pour en savoir plus:

  • Qu'est-ce qui est stocké dans les files / dev / pts et pouvons-nous les ouvrir?

L'autre cas, où je fais des choses comme:

 echo $(ls) a=$(date) vim `command -v some_script` 

est appelé Substitution de command . Dans la substitution de command, la sortie de la command est capturée par le shell lui-même et n'atteint jamais le terminal, sauf si vous l'imprimez (par exemple, echo $(ls) ). Cette affaire est traitée dans la réponse de Hauke ​​Laging .

Il s'avère que j'ai mal compris la question dans le sens de la substitution de command. Seulement dans ce cas, le shell est impliqué dans la gestion de la sortie.

J'espère que cela intéresse aussi …

J'attache à un shell avec strace -p 2140 avant de lancer echo $(/bin/echo foo) dans ce thell. Cela fait partie du résultat:

 pipe([3, 4]) pipe([5, 6]) ... read(3, "foo\n", 128) 

C'est ce qui se passe dans le process enfant:

 dup2(4, 1) close(4) close(3) ... execve("/bin/echo", ... 

Le shell connecte les descripteurs de files 3 et 4, puis les fourches. Le process enfant rend stdout fd 4 avant d'exécuter le nouveau programme. Ainsi, tout ce que l'enfant écrit dans stdout peut être lu par le shell parent sur son fd 3.