Entendendo os redirecionamentos neste comando? [duplicado]

0

Eu encontrei um comando mágico aqui

./my.sh 3>all 1> >(tee out >&3) 2> >(tee err >&3)

Estou confuso em alguns lugares:

  1. O 3>all significa definir o descritor de arquivo 3 para o arquivo all ?
  2. O que 1> > e 2> > ? Pelo que entendi, o comando deve ser ./my.sh 3>all 1>(tee out >&3) 2>(tee err >&3) . Mas isso não funciona.
  3. Por que não (tee err >&3) sobrescreve o arquivo all ?

Este é meu my.sh

#!/bin/bash

echo myecho
ls dflj
    
por yode 10.07.2017 / 09:13

2 respostas

4

Você pode ler sobre esta sintaxe na página man bash sob Substituição de processos :

>(list). The process list is run with its output connected to some file in /dev/fd. The name of this file is passed as an argument to the current command as the result of the expansion.

Veja a saída deste comando que não faz nenhum redirecionamento:

echo >(echo hi >/tmp/a) >(echo lo >/tmp/b)

é (no meu sistema):

/dev/fd/63 /dev/fd/62

Portanto, você deve ler 1> >(...) as 1> e >(...) . A segunda parte é substituída por /dev/fd/63 , e então temos 1> /dev/fd/63 , então redirecionamos o stdout para o descritor de arquivo 63.

bash executa o comando dentro de >(...) em um processo separado e conecta o stdin desse processo ao descritor de arquivo 63. Confira este exemplo:

set -x
echo hello > >(cat -n)

A stdout do eco é canalizada para a entrada de cat -n e você obtém:

+ echo hello
++ cat -n
 1  hello

Talvez o que esteja faltando é que quando você tem um descritor de arquivo (fd) para um arquivo, e então garfo o processo (que o bash está fazendo com >(...) ), você pode herdar o mesmo fd no novo processo. Portanto, os dois processos compartilham o mesmo fd. Além disso, existe apenas um arquivo offset para um fd, então se o processo 1 escreve 3 caracteres para o fd, então o deslocamento se move de 0 para 3. Se o processo 2 então escreve 5 caracteres para o fd, os dados são colocados no deslocamento 3 e o deslocamento se torna 8. Se o processo 1 gravar outro caractere, ele será colocado no deslocamento 8 e assim por diante. É assim que os dois comandos tee em sua pergunta conseguem gravar no mesmo arquivo all sem sobrescrever um ao outro.

Usar >&3 não cria um novo fd; simplesmente fecha o stdout atual fd 1, depois renumera fd 3 para fd 1. Portanto, ainda existe apenas um fd para os dois processos, mesmo se o número agora visto por cada processo for diferente (veja man dup2 para a chamada de sistema subjacente). ).

    
por 10.07.2017 / 09:36
2

Para tentar explicar mais literalmente do que a grande análise teórica do meuh - como você provavelmente já sabe, há vários descritores de arquivos padrão:

  • 0 significa stdin
  • 1 significa stdout
  • 2 significa stderr

O que seu comando faz é o seguinte:

  • 3>all abre um novo descritor de arquivo apontando para o arquivo all
  • 1> >(tee out >&3) redirect stdout ( 1 ) para o descritor de arquivos aberto e retornado pelo comando tee, conforme explicado pelo meuh
    • tee out >&3 redireciona sua entrada (nesse caso, o stdout do seu script) para um arquivo denominado out e onde quer que o descritor de arquivo 3 aponte para (neste caso, o arquivo all)
  • 2> >(tee err >&3) redirect stderr ( 2 ) para o descritor de arquivos aberto e retornado pelo comando tee, conforme explicado pelo meuh
    • tee err >&3 redireciona sua entrada (neste caso, o stderr do seu script) para um arquivo chamado err, e onde quer que o descritor de arquivo 3 aponte para (neste caso, o arquivo all)

A julgar pelo seu comentário, acho que o que está lhe confundindo é que você espera usar o >> como o operador de redirecionamento se quiser anexar a saída a um arquivo.

Este não é o caso aqui, já que tudo o que você está literalmente fazendo é conectar tanto o stdout quanto o stderr ao descritor de arquivo que aponta para o arquivo.

O efeito é o mesmo que fazer:

./my.sh > all 2>&1

Que primeiro redireciona o stdout para o arquivo all e, em seguida, redireciona o stderr para onde stdout estiver apontando.

    
por 10.07.2017 / 14:42