Compreensão de pipeline e redirecionamento

4

Por favor, explique este script (de ABSG. Ch. 20 ):

exec 3>&1                              # Save current "value" of stdout.
ls -l 2>&1 >&3 3>&- | grep bad 3>&-    # Close fd 3 for 'grep' (but not 'ls').
#              ^^^^   ^^^^
exec 3>&-                              # Now close it for the remainder of the script

Atualmente, imagino como isso funciona:

    O script
  1. conecta a saída fd / 3 ao stdout
  2. O pipeline
  3. conecta o stdout de ls ao stdin de grep (o fd / 3 é herdado pelos dois processos)
  4. redirecionamento de stderr de ls para stdout
  5. stdout de ls é alterado para fd / 3 (portanto, grep process não tem mais ls output, apenas erros)
  6. fd / 3 está fechado por ls

Esta é a sequência exata de redirecionamentos?

Não consigo entender por que vejo a saída de ls se não houver erros e fecharmos fd / 3 onde o stdout é redirecionado.

Qual é o propósito de fechar fd / 3 para grep process ( grep bad **3>&-** )?

    
por trupanka 08.08.2013 / 21:26

1 resposta

3

Isso ajuda um pouco se você acha que os descritores de arquivos como variáveis que aceitam um arquivo como um valor (ou o chamam como um fluxo de E / S) e a ordem em que aparecem é a ordem de sua avaliação.

O que acontece no exemplo acima é:

1) O script é iniciado (conforme padrão e, a menos que seja herdado de outra forma) com o seguinte

fd/0 = stdin    # that's the keyboard
fd/1 = stdout   # that's the screen
fd/2 = stderr   # the screen again, but different stream

2) O comando exec traduz a declaração de uma nova variável e a atribuição de um valor

fd/3 = fd/1  # same as stdout

Agora, dois descritores de arquivo têm o valor stdout, ou seja, ambos podem ser usados para imprimir na tela.

3) antes que ls seja executado e herde todos os descritores de arquivos abertos, a seguinte configuração acontece

ls.fd/1 = grep.fd/0    # pipe gets precedence, ls.fd/1 writes to grep.stdin
ls.fd/2 = ls.fd/1      # ls.fd/2 writes to grep.stdin 
ls.fd/1 = ls.fd/3      # ls.fd/1 writes to stdout
ls.fd/3 = closed       # fd/3 will not be inherited by 'ls'

fd / 3 serviu para manter o valor de stdout longo o suficiente para retorná-lo para fd / 1. Então agora tudo o que ls envia para fd / 1 vai para stdout e não para grep 's stdin.

O pedido é importante, por exemplo se executássemos ls -l >&3 2>&1 3>&- , ls.fd / 2 escreveria para stdout em vez de stdin grep .

4) fd / 3 para grep é fechado e não herdado. Não seria usado de qualquer maneira. grep só pode filtrar mensagens de erro de ls

O exemplo fornecido no ABSG provavelmente não é o mais útil e o comentário " Fechar fd 3 para 'grep' (mas não 'ls') " é um pouco enganador. Você pode interpretá-lo como: " para o ls, passe o valor de ls.fd / 3 para ls.fd / 1 antes de desfeito, para que ele não seja fechado ".

    
por 09.08.2013 / 01:26