Como o Bash obtém a saída de um programa executado?

5

Quando executo um programa em Bash , por exemplo, [ls][2] , envia sua saída para saída padrão ( fd &1 ). E a saída do programa executado é exibida no terminal. Como o Bash / terminal obtém a saída do comando ls ?

    
por Max Koretskyi aka Wizard 10.12.2014 / 11:38

2 respostas

9

Como um processo filho do shell, ls herda os descritores de arquivos abertos do shell. E os descritores de arquivo padrão (stdin, stdout, stderr (ou 0, 1, 2)) são conectados a um pseudo-terminal, que é manipulado pelo emulador de terminal.

Por exemplo (em um sistema 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

Ou seja, a saída de ls , ou o próprio shell, não é tratado pelo shell, mas pelo emulador de terminal (Terminal GNOME, terminator, xterm, etc.).

Você pode testar isso:

No Linux, encontre um pseudoterminal ( pts ) usado pelo emulador de terminal (digamos, 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

Agora, os fds não-padrão (aqueles diferentes de 0,1,2) de gnome-terminal seriam usados por ele para fornecer entrada e saída para um shell. O emulador de terminal lê os dados enviados para esse PTS e (após algum processamento, para cores e outros) o apresenta na tela. Nesse caso, isso seria 15 , conectado a pts/20 . Se eu escrever algo nesses pts, posso esperar que apareça nesse terminal:

Leituraadicional:

  • O que está armazenado em arquivos / dev / pts e podemos abri-los?

O outro caso, onde faço coisas como:

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

é chamado de Substituição de Comando . Na substituição de comando, a saída do comando é capturada pelo próprio shell e nunca chega ao terminal, a menos que você o imprima (por exemplo, echo $(ls) ). Este caso é tratado na resposta de Hauke Laging .

    
por 10.12.2014 / 11:48
3

Acontece que eu não entendi a pergunta no sentido de substituição de comando. Somente nesse caso, o shell está envolvido no processamento de saída.

Espero que isso seja interessante também ...

Eu atribuo a um shell com strace -p 2140 antes de executar echo $(/bin/echo foo) neste arquivo. Isso faz parte do resultado:

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

Isso é o que acontece no processo filho:

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

O shell conecta os descritores de arquivo 3 e 4 e, em seguida, os garfos. O processo filho torna o fd 4 seu stdout antes de executar o novo programa. Assim, tudo o que o filho grava em stdout pode ser lido pelo shell pai em seu fd3.

    
por 10.12.2014 / 12:21