Note that the order of redirections is significant. For example, the command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist,
while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the
standard error was duplicated from the standard output before the standard
output was redirected to dirlist.
Agora, essa última parte é confusa para mim. Nesse caso, qualquer erro padrão seria impresso no terminal e qualquer STDOUT iria para o arquivo dirlist. Isso é o que aconteceria, mas não é assim que eu entendo o manual.
Parece que deveria dizer "porque o erro padrão foi duplicado da saída padrão APÓS a saída padrão foi redirecionada para dirlist". Se STDERR foi enviado para STDOUT antes que STDOUT fosse direcionado para um arquivo, o arquivo não conteria STDOUT AND STDERR?
Alguém pode esclarecer isso para mim? É apenas pouca compreensão de leitura da minha parte? O uso da palavra duplicação me parece um pouco estranho nesse contexto. Talvez isso esteja me jogando.
bash
shell
io-redirection
Gregg Leventhal
fonte
fonte
a = 1; b = a; a = 2
você esperaa == 2 && b == 1
ser verdade. O redirecionamento2>&1
é semelhante àb = a
atribuição - é por valor, não por referência.2>&1
não se encaixa no descritor de arquivo 2 para o descritor de arquivo 1 por toda a eternidade - eles ainda são 2 descritores de arquivo distintos, que apontam para o mesmo arquivo.Respostas:
A duplicação é realmente a parte importante aqui.
Vamos ver para onde os descritores de arquivo estão indo antes do redirecionamento. Normalmente, este é o terminal atual, por exemplo:
Agora, se ligarmos
ls -l
sem redirecionamento, as mensagens de saída e de erro vão para o meu terminal em/dev/pts/1
.Se primeiro redirecionarmos
STDOUT
para um arquivo (ls -l > dirlist
), será assim:Quando , em seguida, redirecionar
STDERR
a um duplicado deSTDOUT
descritor de arquivo 's (ls -l > dirlist 2>&1
),STDERR
vai para uma cópia de/home/bon/dirlist
:Se primeiro redirecionarmos
STDERR
para uma duplicata doSTDOUT
descritor de arquivo (ls -l 2>&1
):e depois
STDOUT
para um arquivo (ls -l 2>&1 > dirlist
), teríamos o seguinte:Aqui,
STDERR
ainda está indo para o terminal.Veja bem, a ordem na página de manual está correta.
Redirecionando testes
Agora, você pode testar isso sozinho. Usando
ls -l /proc/$$/fd/
, você vê ondeSTDOUT
(com fd 1) eSTDERR
(com fd 2) estão indo para o processo atual:Vamos criar um pequeno script de shell que mostre para onde os descritores de arquivos estão apontados. Dessa forma, sempre obtemos o estado ao chamar
ls
, incluindo qualquer redirecionamento do shell de chamada.(Com CtrlD, você envia um final de arquivo e, portanto, interrompe a
cat
leitura do comandoSTDIN
.)Agora, chame esse script com combinações variadas de redirecionamento:
Você pode ver que os descritores de arquivo 1 (para
STDOUT
) e 2 (paraSTDERR
) variam. Por diversão, você também pode redirecionarSTDIN
e ver o resultado:(Pergunta deixada ao leitor: Onde o descritor de arquivos 255 aponta? ;-))
fonte
Não, o manual está certo.
Se no começo 1 apontar para o terminal e 2 também para o terminal, então:
o redirecionamento de avaliação acontecerá da esquerda para a direita.
Portanto, ele PRIMEIRO avaliará
2>&1
e, portanto, PRIMEIRO copiará o que fd1
costumava apontar (isto é, o descritor de arquivothe terminal
, geralmente / dev / tty) para fd2
.Então, nesse ponto, o fd
2
agora aponta para onde o fd1
costumava apontar (the terminal
)E então ele avalia a
1>somewhere
parte e, assim, copia o descritor de arquivo desomewhere
em fd1
(então, nesse ponto, fd1
agora aponta parasomewhere
e fd2
ainda aponta parathe terminal
)Por isso, imprime 1 em "algum lugar" e 2 no terminal, pois 2 foi duplicado de 1 ANTES de 1 ter sido alterado.
A outra ordem:
primeiro redirecionará fd
1
parasomewhere
e depois copiará a mesma referência para fd 2; portanto, no final 2 também aponte parasomewhere
. Mas eles não estão "ligados" a partir de agora. Cada um ainda pode ser redirecionado separadamente.ex:
No final desse, fd
1
aponta parasomewhere
, e fd2
é direcionado para/dev/null
Os nomes comuns para fd
1
são STDOUT (saída padrão) e o nome usual para fd2
é STDERR (erro padrão, pois é comumente usado para exibir erros sem interferir no STDOUT)fonte
cmd 1>somewhere 2>&1 ; exec 2>/dev/null
após o exec, apenas 2 foram redirecionados para / dev / null (1 ainda está indo para "algum lugar"). Eu preciso de ajuda para encontrar uma maneira de dizer "o que 1 aponta para" em vez de "o fd 1", no entanto ... como isso também é confuso ...Acho que a parte confusa aqui é a má compreensão de que o redirecionamento de stderr para stdout realmente conecta os dois fluxos.
Uma ideia perfeitamente razoável, mas o que acontece quando você escreve
2>&1
é stderr dá uma olhada no que stdout está escrevendo e escreve no mesmo local. Portanto, se você pedir ao stdout para escrever em outro lugar, isso não afetará o destino do stderr que já foi movido.Eu acho que é um pouco contra-intuitivo, mas é assim que funciona. Configure onde você deseja escrever primeiro e depois diga a todos "me copie". Espero que esclareça ...
fonte
DUPLICAÇÃO...
é importante, mas no sentido de que é fonte de muita confusão . É realmente muito simples. Esta resposta é apenas uma ilustração "radical".
A resposta aceita é boa, mas longa demais e enfatiza a "duplicação".
O Q termina sabiamente com:
Uso a notação bash e defino as variáveis "um" e "dois" como identificadores de arquivo "1" e "2". O operador de redirecionamento (de saída)
>
é uma atribuição=
.&
e$
significa "valor" de.Os exemplos do man bash (com o padrão "1" adicionado)
tornar-se:
e
E mesmo isso não é automático para mim, e para alguns outros, eu acho. A primeira linha deixa você com
$one
e$two
ambos contendo "dirlist". Claro.A segunda linha começa com uma atribuição inútil. Ambos começam por definição com "TTY" (um pouco simbólico) como direção ; nenhum valor é alterado por essa atribuição e, com variáveis como com identificadores de arquivo, nada é vinculado magicamente. A variável
two
não é afetada pelo seguinteone=dirlist
. Claro que não.Sombody aqui (há 6 anos) sugeriu "apontar para" em vez de "copiar" ou "duplicar" e depois percebeu: isso também seria confuso.
Essa duplicação ou semântica de ponteiros nem é necessária. Talvez seja o e comercial que precise de mais atenção. O "valor de" operador / token / qualquer coisa.
Se - e somente se - você estiver procurando uma maneira de obter um número surpreendente de tarefas no seu console , uma mensagem "concluído" e um bônus como um arquivo chamado "2" serão exibidos :
Lê naturalmente como " copiar" / "duplicar" 1 a 2 e, em seguida, ambos juntos para nulo . Mas a ideia está errada, e também a sintaxe. (mas nenhum erro de sintaxe, é válido)
A maneira correta de planejar é redirecionar qualquer um dos dois para null e, em seguida, redirecionar o OTHER para o MESMO local:
(o "1" principal pode ser deixado de fora)
(OK, o acesso A não é muito longo, mas é muito uma lista - ou: visualização muito boa, explicação não muito boa)
fonte