Entendendo o redirecionamento de i / o no contexto de _processo de substituição_

5

Executando o GNU bash, versão 4.3.11 (1) -release (x86_64-pc-linux-gnu).

Eu realmente não entendo substituição de processos (ProcSub) da perspectiva de um usuário interessado em levantar o capô no processamento de i / o e problemas de velocidade relacionados. Eu uso ProcSub para script, então eu tenho algum conhecimento de descritores de arquivo 0,1,2, mas isso é muito bonito. Eu li alguns posts muito bons, por exemplo [1] e misc. wikis, e. [2] , [3] , o último afirmando: " A substituição do processo alimenta a saída (FD 1 e / ou 2) de um processo (ou processos) no stdin (FD 0) de outro processo ". Por essa definição mais simples e por apenas um processo, não parece operacionalmente diferente de um simples pipe não nomeado.

Para investigar, comecei com tee , por si só interessante do ponto de vista de i / o.
tee permite alimentar "stdin stdout e também para quaisquer arquivos fornecidos como argumento ". Então:

$ for i in 1 2 3; do (( j=i+10 )); printf "%d\n" $j > file_$i; done
# so each file in file_{1,2,3} contains the numeral in its name + 10.
$ cat file_{1,2,3} | tee file_4
11
12
13
$ cat file_4
11
12
13

Obviamente, não estou interessado em ver os dados preenchendo minha tela como o Matrix, então:

1) Eu adiciono um pipe e redirecionamento da saída de shasum ...

$ cat file_{1,2,3} | tee file_4 | shasum -a 256 > file_4.sha256
$ 

o um forro acima sai silenciosamente , o arquivo_4 é como antes (acima) e o arquivo_4.sha256 contém a soma SHA256 calculada.

O acima é apenas um exemplo para ilustrar a minha pergunta, tentando entender o i / o intermediário. A conclusão de meu leigo é que tee salva a saída de cat cmd em file_4 e sua cópia normalmente enviada para stdout não é enviada para stdout, mas canalizada para shasum .
Q: Isso está remotamente certo?

2) Eu tento o mesmo com ProcSub:

$ cat file_{1,2,3} | tee file_4 >(shasum -a 256 > file_4.sha256)
11
12
13
$ 

- > Nenhum redirecionamento stdout do que está sendo enviado para o FD 1 por tee ?

P: Não estou claro sobre o que o ProcSub faz ou não para a i / o (obviamente, isso não afeta a E / S neste caso) e poderia usar uma explicação de seu mecanismo.

3) Eu tento com o ProcSub e o redirecionamento da stdout final para file_4:

$ cat file_{1,2,3} | tee >(shasum -a 256 > file_4.sha256) > file_4
$ 

Novamente, desta vez, o one-liner existe em silêncio.

P: Portanto, a pergunta geral é: como eu sou processado para os 3 casos acima (ou pelo menos para o segundo e o terceiro)? Existem diferenças óbvias e visíveis nos termos de E / S (apenas olhando para a stdout final), mas às vezes diferentes processos de E / S podem levar a resultados finais idênticos na tela. Tx.

    
por Cbhihe 15.01.2016 / 16:38

2 respostas

5

O idioma >(...) significa apenas (em termos leigos): "o nome de um arquivo".

E funciona como um "nome de um arquivo" (mais ou menos tudo ficará claro em um instante):

$ echo <(date)
/proc/self/fd/11

Ou algum outro número / nome no seu sistema operacional. Mas o eco imprime um nome, exatamente como se você fizesse:

$ echo ProcSubs11
ProcSubs11

E se existir um arquivo com o rótulo ProcSubs11, você também pode:

$ cat ProcSubs11
contents_of_file_ProcSubs11

Que você poderia fazer exatamente o mesmo com:

$ cat <(date)
Fri Jan 15 21:25:18 UTC 2016

A diferença é que o nome real da "Substituição do Processo" é "não visível" e que os detalhes são muito maiores do que ler um arquivo simples, como descrito bem em todos os detalhes dolorosos no link Como a substituição do processo é implementada no bash? .

Tendo dito o acima, vamos analisar seus itens.

Q 1

...seems operationally no different from a simple unnamed pipe...

Bem, a "Substituição de processos" é baseada exatamente em um unnamed pipe , pois o primeiro primeiro link declara:

  1. The bash process creates an unnamed pipe for communication between the two processes created later.

A diferença é que todas as ~ 6 etapas explicadas no link são simplificadas para um idioma >(...) para gravação para e <(...) para leitura de .

E, pode-se argumentar que a conexão (pipe) tem um nome, como um arquivo tem. Só que esse nome está oculto do usuário (o /proc/self/fd/11 mostrado no começo).

Exemplo 1

1) I add a pipe and redirection of shasum's output ...

$ cat file_{1,2,3} | tee file_4 | shasum -a 256 > file_4.sha256

Não há "Substituição de processo", mas vale a pena notar (para depois) que tee envia (escreve para) o que recebe em seu stdin para um arquivo file_4 e também envia o mesmo conteúdo de stdin para stdout . Que acontece de estar conectado a um pipe (neste caso) que escreve no shasum.

Portanto, em suma, em termos leigos, copie o tft stdin para ambos file_4 e shasum .

Exemplo 2

2) I try the same with ProcSub:

$ cat file_{1,2,3} | tee file_4 >(shasum -a 256 > file_4.sha256)

Reutilize a descrição acima (em termos leigos) para descrever este exemplo:

Copie stdin para três elementos: file_4 , shasum e stdout .

Por quê? Lembre-se que >(...) é o nome de um arquivo, vamos colocar isso na linha:

$ cat file_{1,2,3} | tee file_4 /proc/self/fd/11

tee está servindo a entrada para dois arquivos file_4 e shasum (via "Substituição de processo") e o stdout de tee ainda está conectado ao local padrão: o console. É por isso que você vê os números no console.

Para tornar este exemplo exatamente igual a 1) , poderíamos fazer:

$ cat file_{1,2,3} | tee file_4 > /proc/self/fd/11  ### note the added '>'

O que se torna (sim, o espaço entre > e >( deve ser usado.

$ cat file_{1,2,3} | tee file_4 > >(shasum -a 256 > file_4.sha256)

Isso está redirecionando o stdout de tee para a "Substituição do processo".

Q 3

Q: So the general question is: how are i/o processed for the 3 cases above

Acredito que acabei de explicar os 3 casos, se não for claro, por favor comente.

Q 4 (nos comentários, edite e adicione a pergunta)

why the <(...) construct won't work in the third case.

Porque (em termos leigos) você não pode inserir um macho em uma tomada masculina .

O idioma < (...) lê a partir do que está dentro da "Substituição do processo" e, portanto, fornece uma "saída" e deve ser inserido no stdin do comando externo. O comando externo tee está tentando conectar elementos stdout (like). Então, esse par não poderia corresponder.

Uma importante nota : O comando cat oculta alguns detalhes quando aplicado a "Substituição de processos", pois ambos os comandos fornecerão a mesma saída:

$ cat   <(date)
$ cat < <(date)

Tudo está correto, mas tirar conclusões de uma igualdade enganosa é errado.

    
por 15.01.2016 / 23:26
4

it seems operationally no different from a simple unnamed pipe.

O ponto é que nem todo software suporta a leitura de stdin ou escrita para stdout.

Além disso, se você quiser inserir vários processos, não poderá diferenciá-los (sem olhar para os dados em si) com apenas um canal:

{ echo foo; echo bar; } | cat
# vs.
cat <(echo foo) <(echo bar)

com cat obviamente sendo um mau exemplo. Mas com awk pode fazer a diferença ( FNR vs. NR ).

2)

tee file_4 >(shasum -a 256 > file_4.sha256)

No stdout redirection of whatever being sent to FD 1 by tee?

Não, por que deveria haver? >(cmd) não não significa "redirecionar stdout"! Portanto, há um comando sem redirecionamento. No caso 3) você adiciona redirecionamento ao comando e a saída é redirecionada.

Você pode usar isso para entender melhor suas linhas de comando:

echo tee file_4 >(shasum -a 256 > file_4.sha256)
    
por 15.01.2016 / 19:09