Tentando entender as sintaxes de redirecionamento do bash e suas saídas

5

Sou novo no Linux e estou tentando entender como os redirecionamentos funcionam.

Eu tenho testado várias sintaxes para redirecionar stdout e stderr para o mesmo arquivo, o que não produz todos os mesmos resultados.

Por exemplo, se eu tentar listar 2 arquivos que não existem ( file1 e file2 ) e 2 que não existem ( foo e fz ):

Sintaxe # 1 (sem redirecionamento):

$ ls file1 foo fz file2

Aqui está a saída que recebo no terminal:

ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo  fz

Sintaxe # 2:

Agora, com redirecionamento:

$ ls file1 foo fz file2 > redirect 2>&1

O arquivo redirect contém o mesmo resultado da Sintaxe # 1:

ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo
fz

Portanto, com as duas sintaxes acima, parece que o shell imprime stderr primeiro e, em seguida, stdout .

Sintaxe # 3:

Agora, se eu tentar com uma das seguintes sintaxes:

$ ls file1 foo fz file2 > redirect 2> redirect

ou

$ ls file1 foo fz file2 2> redirect > redirect

Em seguida, o arquivo redirect conterá isso:

foo
fz
nnot access file1: No such file or directory
ls: cannot access file2: No such file or directory

Aqui, parece que stdout é impresso antes de stderr , mas depois vemos que o início de stderr é "recortado" pelo mesmo número de caracteres que stdout .

O stdout tem 6 caracteres ( foo fz , retorno de carro incluído), portanto, os primeiros 6 caracteres de stderr ( ls: ca ) foram substituídos por stdout . Portanto, parece que stderr foi impresso primeiro e que stdout foi impresso sobre stderr em vez de ser anexado a ele.

No entanto, teria feito mais sentido para mim se stderr tivesse sido completamente apagado e substituído por stdout , em vez de ser apenas parcialmente substituído.

Sintaxe # 4:

A única maneira que encontrei para corrigir a Sintaxe # 3 é adicionando o operador append ao stdout :

$ ls file1 foo fz file2 >> redirect 2> redirect

ou

$ ls file1 foo fz file2 2> redirect >> redirect

Que produz o mesmo que a sintaxe # 2:

ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo
fz

Este artigo aqui explica que a sintaxe # 3 está errada (presumivelmente, assim é a sintaxe # 4). Mas, por razões de argumentação: por que a sintaxe nº 3 está errada? O que exatamente está dizendo (ou não dizendo) o shell para fazer em oposição à Sintaxe # 2?

Além disso, há uma razão pela qual a saída sempre exibe stderr antes de stdout ?

Obrigado!

    
por LePoufCelebre 11.03.2016 / 02:00

3 respostas

6

É como executar dois processos para gravar no mesmo arquivo ao mesmo tempo ... má idéia. Você acaba com duas diferentes alças de arquivos abertos e seus dados podem ficar distorcidos (como acontece no item 3 acima). Usando a sintaxe # 2 está correto; faz com que o um identificador de arquivos e aponte stderr e stdout para o mesmo lugar.

Quanto a stderr sempre sendo impresso primeiro, não há nenhuma regra sobre isso. Eu suspeito que com ls é porque ls precisa verificar cada entrada no diretório antes que ele possa realmente afirmar que um determinado arquivo não existe. Portanto, em vez de fazer N passar pela tabela de diretórios, ele faz uma única passagem, verificando todos os argumentos da linha de comando, relatando os erros e imprimindo os arquivos encontrados. Outros comandos podem imprimir para stderr após stdout, ou alternar entre eles.

    
por 11.03.2016 / 02:18
6

Adicionando à resposta curinga, stdout é geralmente armazenado em buffer (armazenado na memória para ser escrito posteriormente), enquanto stderr nunca é (você deseja que mensagens de erro apareçam, mesmo que o programa falhe antes de gravar alguma coisa) . Então, stderr geralmente aparece mais cedo.

    
por 11.03.2016 / 03:08
2

Não é um desenvolvedor aqui ou um especialista em kernel. Então eu não posso comentar sobre qualquer código, mas na sintaxe # 3 você está canalizando stdout e stderr para o mesmo arquivo usando dois canais diferentes. Portanto, o arquivo comum para o qual você está enviando as duas saídas está possivelmente tendo problemas de contenção de recursos de dois canais diferentes. Considerando a natureza do sistema operacional em tempo não real, dois canais estão fornecendo informações para o mesmo arquivo, provavelmente ao mesmo tempo. O que pode explicar personagens ausentes.

Na sintaxe # 2, você está redirecionando o stderr para o mesmo canal para stdout . Nesse ponto, o arquivo tem um canal chegando e o shell gerencia esse canal em relação às condições de corrida.

Este é o meu palpite e apenas um palpite. Nada para fundamentar isso.

    
por 11.03.2016 / 02:15