Pergunta

Em um shell Unix, se eu quiser combinar stderr e stdout na corrente stdout para posterior manipulação, posso acrescentar o seguinte no final do meu comando:

2>&1

Então, se eu quiser usar head na saída de g++, eu posso fazer algo como isto:

g++ lots_of_errors 2>&1 | head

para que eu possa ver apenas os primeiros erros.

Eu sempre tenho dificuldade em lembrar isso, e eu constantemente tem que ir procurá-lo, e é principalmente porque eu não compreender totalmente a sintaxe deste truque particular.

Pode alguém quebrar isso e explicar caractere por caractere meios que 2>&1?

Foi útil?

Solução

descritor de arquivo 1 é a saída padrão (stdout).
descritor de arquivo 2 é o erro padrão (stderr).

Aqui está uma maneira de lembrar esta construção (embora não seja inteiramente exato): em primeiro lugar, 2>1 pode parecer uma boa maneira de stderr redirecionamento para stdout. No entanto, ele vai realmente ser interpretado como "stderr redirecionamento para um 1 arquivo chamado". & indica que o que se segue é um descritor de arquivo e não um nome de arquivo. Assim, a construção torna-se:. 2>&1

Outras dicas

echo test > afile.txt

redirecionamentos stdout para afile.txt. Este é o mesmo que fazer

echo test 1> afile.txt

Para redirecionar stderr, você faz:

echo test 2> afile.txt

>& é a sintaxe para redirecionar um fluxo para outro descritor de arquivo -. 0 é stdin, 1 é stdout e 2 é stderr

Você pode redirecionar stdout para stderr fazendo:

echo test 1>&2 # or echo test >&2

Ou vice-versa:

echo test 2>&1

Assim, em ... curto 2> redirecionamentos stderr para um arquivo (não especificado), anexando redirecionamentos &1 stderr para stdout.

Alguns truques sobre o redireccionamento

Alguns particularidade de sintaxe sobre isso pode ter comportamentos importantes. Há algumas amostras pouco sobre redirecionamentos, STDERR, STDOUT e argumentos ordenação .

1 - substituir ou anexando?

Símbolo > média redirecionamento .

  • > média Enviar como um arquivo concluída toda , alvo sobrescrevendo, se existe (ver destaque noclobber bash no # 3 mais tarde).
  • >> média send além seria anexar a meta, se existir.

Em qualquer caso, o arquivo seria criado se não existir.

2 - A ordem linha de comando shell é dependente !!

Para testar isso, precisamos um simples comando que irá enviar algo em ambas as saídas :

$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

(Esperando que você não tem um diretório chamado /tnt, é claro;). Bem, nós temos isso !!

Então, vamos ver:

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1

$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory

A última linha de comando despeja STDERR para o console, e não parece ser o comportamento esperado ... Mas ...

Se você quiser fazer algum filtragem pós sobre uma saída, a outra ou ambas:

$ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'

$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->

Observe que a última linha de comando neste parágrafo é exatamente o mesmo que no parágrafo anterior, onde eu escrevi não parecem ser o comportamento esperado (assim, isso poderia até ser um comportamento esperado).

Bem, há um pouco de truques sobre redirecionamentos, por fazendo operação diferente em ambas as saídas :

$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2  2>&1  | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan  7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory

Nota:. Descritor &9 ocorreria espontaneamente por causa da ) 9>&2

Adenda: nota Com a nova versão do (>4.0), há um novo recurso e sintaxe mais sexy para fazer este tipo de coisas:

$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory

E, finalmente, para a formatação de tal saída uma cascata:

$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
     1  O: drwxrwxrwt 118 root root 196608 Jan  7 12:29 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

Adenda: nota Mesma nova sintaxe, em ambos os sentidos:

$ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
     1  O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

Onde STDOUT passar por um filtro específico, STDERR para outro e, finalmente, as duas saídas fundiu passar por um filtro de comando terceiro.

3 - Uma palavra sobre a opção noclobber e >| sintaxe

Isso é cerca de substituição :

Enquanto set -o noclobber instruir bash para não substituir qualquer arquivo existente, o >| sintaxe deixá-lo passar por esta limitação:

$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:15 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:19 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:21 CET 2013

O arquivo é sobrescrito cada vez, bem agora:

$ set -o noclobber

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

Passe adiante com >|:

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:18:58 CET 2013

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:19:01 CET 2013

A desactivação desta opção e / ou perguntando se já definido.

$ set -o | grep noclobber
noclobber           on

$ set +o noclobber

$ set -o | grep noclobber
noclobber           off

$ date > $testfile ; cat $testfile
Mon Jan  7 13:24:27 CET 2013

$ rm $testfile

4 - Última truque e mais ...

Para redirecionando ambos saída de um comando dado, vemos que uma sintaxe direita poderia ser:

$ ls -ld /tmp /tnt >/dev/null 2>&1

para este especial caso, há uma sintaxe atalho: &> ... ou >&

$ ls -ld /tmp /tnt &>/dev/null

$ ls -ld /tmp /tnt >&/dev/null

Nota: se 2>&1 exist, 1>&2 é uma sintaxe correta demasiado:

$ ls -ld /tmp /tnt 2>/dev/null 1>&2

4b- Agora, eu vou deixar você pensar:

$ ls -ld /tmp /tnt 2>&1 1>&2  | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

$ ls -ld /tmp /tnt 1>&2 2>&1  | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

4c- Se você estiver interessado em mais informações

Você pode ler o manual fina por bater:

man -Len -Pless\ +/^REDIRECTION bash

consola; -)

Eu encontrei este post brilhante no redirecionamento: tudo sobre redirecionamentos

Redirect tanto a saída padrão e erro padrão para um arquivo

$ comando &> arquivo

Este one-liner usa o operador &> para redirecionar ambos os fluxos de saída - stdout e stderr - de comando para arquivo. Esta é atalho do Bash para redirecionar rapidamente ambos os fluxos para o mesmo destino.

Aqui está como a tabela descritor de arquivo parece que depois Bash redirecionou ambos os fluxos:

 Digite os detalhes da imagem aqui

Como você pode ver, ambos stdout e stderr agora apontam para file. Então, qualquer coisa escrita para stdout e stderr é gravado file.

Existem várias maneiras de redirecionar ambos os fluxos para o mesmo destino. Você pode redirecionar cada um córrego após o outro:

$ command> arquivo 2> & 1

Esta é uma maneira muito mais comum para redirecionar ambos os fluxos em um arquivo. Primeiro stdout é redirecionada para o arquivo, e depois stderr é duplicado para ser o mesmo que stdout. Assim, ambos os fluxos acabam apontando para file.

Quando Bash vê vários redirecionamentos ele processa-los da esquerda para a direita. Vamos percorrer os passos e ver como isso acontece. Antes de executar quaisquer comandos, da festança de descritor de arquivo da tabela esta aparência:

 Digite os detalhes da imagem aqui

Agora Bash processa o primeiro redirecionamento> arquivo. Nós já vimos isso antes e isso faz ponto stdout para o arquivo:

 Digite os detalhes da imagem aqui

A seguir Bash vê o segundo redirecionamento 2> & 1. Nós não vimos esse redirecionamento antes. Este descritor um arquivo duplicatas 2 para ser uma cópia do descritor de arquivo 1 e obtemos:

 Digite os detalhes da imagem aqui

Ambos os fluxos foram redirecionados para arquivo.

No entanto ter cuidado aqui! Escrevendo

command> arquivo 2> & 1

não é o mesmo que escrever:

$ comando 2> & 1> arquivo

A ordem de redirecionamentos importa na Bash! Este comando redireciona apenas a saída padrão para o arquivo. O stderr ainda será impresso para o terminal. Para entender por que isso acontece, vamos percorrer as etapas novamente. Portanto, antes de executar o comando, a tabela descritor de arquivo esta aparência:

 Digite os detalhes da imagem aqui

Agora Bash processa redirecionamentos esquerda para a direita. Ele vê pela primeira vez 2> & 1 para que ele duplica stderr para stdout. A tabela descritor de arquivo torna-se:

 Digite os detalhes da imagem aqui

Agora Bash vê o segundo redirecionamento, >file, e ele redireciona stdout para o arquivo:

 Digite os detalhes da imagem aqui

Você vê o que acontece aqui? Stdout agora aponta para arquivo, mas o stderr ainda aponta para o terminal! Tudo o que é escrito para stderr ainda será impresso para a tela! Portanto, tenha muito, muito cuidado com a ordem de redirecionamentos!

Observe também que em Bash, escrito

$ comme &> arquivo

é exatamente o mesmo que:

$ command> & arquivo

Os números referem-se os descritores de arquivo (FD).

  • Zero é stdin
  • Uma é stdout
  • Dois é stderr

2>&1 redirecionamentos fd 2 a 1.

Isso funciona para qualquer número de descritores de arquivos se o programa usa-los.

Você pode olhar para /usr/include/unistd.h se você esquecê-los:

/* Standard file descriptors.  */
#define STDIN_FILENO    0   /* Standard input.  */
#define STDOUT_FILENO   1   /* Standard output.  */
#define STDERR_FILENO   2   /* Standard error output.  */

Dito isto eu escrevi ferramentas C que usam descritores de arquivos não-padrão para o registo personalizado para que você não vê-lo a menos que você redirecioná-lo para um arquivo ou algo assim.

Essa construção envia o fluxo de erro padrão (stderr) ao atual localização da saída padrão (stdout) -. Esta questão cambial parece ter sido negligenciado por outras respostas

Você pode redirecionar qualquer alça de saída para outro usando este método, mas é mais frequentemente usado para stdout canal e stderr córregos em um único fluxo para processamento.

Alguns exemplos são:

# Look for ERROR string in both stdout and stderr.
foo 2>&1 | grep ERROR

# Run the less pager without stderr screwing up the output.
foo 2>&1 | less

# Send stdout/err to file (with append) and terminal.
foo 2>&1 |tee /dev/tty >>outfile

# Send stderr to normal location and stdout to file.
foo >outfile1 2>&1 >outfile2

Note que esse último irá não stderr direta com outfile2 - ele redireciona-lo para o que stdout foi quando o argumento foi encontrado (outfile1) e então redirecionamentos stdout para outfile2 .

Isso permite que alguns truques muito sofisticado.

2>&1 é uma construção POSIX shell. Aqui está uma repartição, token token:


2:. " Erro padrão " descritor de arquivo de saída

>&: Duplicar um arquivo de saída descritor operador (uma variante do saída Redirecionamento operador >). Dada [x]>&[y], o descritor de arquivo denotado por x é feito para ser uma cópia do y descritor de arquivo de saída.

1 " A saída padrão " descritor de arquivo de saída.

O descritor de arquivo expressão 2>&1 cópias 1 para 2 localização, portanto, qualquer saída escrito para 2 ( "erro padrão") no ambiente de execução vai para o mesmo arquivo originalmente descrita por 1 ( "saída padrão").


Além disso explicação:

Arquivo Descritor : "um por processo único inteiro, não negativo usado para identificar um arquivo aberto com a finalidade de acesso ao arquivo."

A saída padrão / erro : rel Consulte a seguinte nota no seção da documentação shell redirecionamento :

Abrir arquivos são representados por números decimais começando com zero. O maior valor possível é definido pela implementação; no entanto, todas as implementações devem suportar pelo menos 0-9, inclusive, para uso pela aplicação. Estes números são chamados de "descritores de arquivos". Os valores 0, 1, e 2 têm um significado especial e usos convencionais e são implícitos em certas operações de redireccionamento; eles são referidos como padrão de entrada, de saída padrão, e o erro padrão, respectivamente. Programas geralmente levam a sua entrada da entrada padrão e escrever a saída na saída padrão. Mensagens de erro são geralmente escritos em caso de erro padrão. Os operadores de redirecionamento pode ser precedida por um ou mais dígitos (sem caracteres intervenientes permitido) para designar o número descritor de arquivo.

2 é o erro padrão console.

1 é a saída padrão do console.

Este é o padrão do Unix e Windows também segue o POSIX.

por exemplo. quando você executar

perl test.pl 2>&1

o erro padrão é redirecionado para a saída padrão, para que possa ver ambas as saídas em conjunto:

perl test.pl > debug.log 2>&1

Após a execução, você pode ver toda a saída, incluindo erros, na debug.log.

perl test.pl 1>out.log 2>err.log

Em seguida, a saída padrão vai para out.log, e erro padrão para err.log.

Eu sugiro que você tente entender estes.

Para responder à sua pergunta: É preciso qualquer saída de erro (normalmente enviado para stderr) e escreve para a saída padrão (stdout).

Isso é útil, por exemplo 'mais' quando você precisa de paginação para todas as saídas. Alguns programas como imprimir as informações de uso em stderr.

Para ajudar a lembrar

  • 1 = saída padrão (onde os programas de imprimir a saída normal)
  • 2 = erro padrão (onde os programas de imprimir erros)

"2> & 1" simplesmente aponta tudo enviado para stderr, para stdout em vez.

Eu também recomendo a leitura este post em caso de erro redirecionando onde esta assunto é coberto em detalhes.

Do ponto de vista de um programador, isso significa precisamente isto:

dup2(1, 2);

Veja a página homem .

Entendendo que 2>&1 é uma cópia também explica por que ...

command >file 2>&1

... não é o mesmo que ...

command 2>&1 >file

O primeiro irá enviar ambos os fluxos para file, enquanto o segundo irá enviar erros para stdout e saída comum em file.

People, lembre-se sempre paxdiablo 's dica sobre o atual localização do alvo redirecionamento ... É é importante.

O meu mnemônico pessoal para o operador 2>&1 é esta:

  • Pense & no sentido 'and' ou 'add' (o personagem é uma ampers -? e , não é)
  • Assim torna-se: 'redirecionamento 2 (stderr) para onde 1 (stdout) já / atualmente é e Adicionar ambos os fluxos'
  • .

As mesmas obras mnemônicas para o outro redirecionamento usado com freqüência também, 1>&2:

  • Pense & significando and ou add ... (você começa a idéia sobre o comercial, sim?)
  • Assim torna-se: 'redirecionamento 1 (stdout) para onde 2 (stderr) já / atualmente é e Adicionar ambos os fluxos'
  • .

E lembre-se sempre:. Você tem que ler cadeias de redirecionamentos 'do fim', da direita para a esquerda ( não da esquerda para a direita)

Desde que /foo não existe no seu sistema e /tmp faz ...

$ ls -l /tmp /foo

irá imprimir o conteúdo de /tmp e imprimir uma mensagem de erro para /foo

$ ls -l /tmp /foo > /dev/null

irá enviar o conteúdo de /tmp para /dev/null e imprimir uma mensagem de erro para /foo

$ ls -l /tmp /foo 1> /dev/null

vai fazer exatamente o mesmo (note o 1 )

$ ls -l /tmp /foo 2> /dev/null

irá imprimir o conteúdo de /tmp e enviar a mensagem de erro para /dev/null

$ ls -l /tmp /foo 1> /dev/null 2> /dev/null

enviará tanto o listando bem como a mensagem de erro para /dev/null

$ ls -l /tmp /foo > /dev/null 2> &1

é um atalho

Este é apenas como passar o erro para o stdout ou do terminal.

Isto é, cmd não é um comando:

$cmd 2>filename
cat filename

command not found

O erro é enviada para o arquivo como este:

2>&1

O erro padrão é enviada para o terminal.

Redirecionando entrada

Redirecionamento de entrada faz com que o arquivo cujo nome resulta da expansão da palavra a ser aberto para leitura em arquivo descritor n, ou a entrada padrão (descritor de arquivo 0) se n for não especificado.

O formato geral para redirecionar entrada é:

[n]<word

Redirecionando a saída

O redirecionamento da produção faz com que o arquivo cujo nome resulta da expansão da palavra a ser aberto para gravação em descritor n arquivo ou a saída padrão (descritor de arquivo 1) se n não é especificado. Se o arquivo não existir, ele é criado; Se isso existe é truncado para o tamanho zero.

O formato geral para redirecionar a saída é:

[n]>word

Arquivo Movimento Descritores

O operador de redirecionamento,

[n]<&digit-

move o dígito descritor de arquivo de descritor de arquivo n, ou a entrada padrão (descritor de arquivo 0) se n não é especificado. dígito é fechado depois de ser duplicada para n.

Da mesma forma, o operador de redirecionamento

[n]>&digit-

move o dígito descritor de arquivo de descritor de arquivo n, ou a saída padrão (descritor de arquivo 1) se n não é especificado.

Ref:

man bash

Tipo /^REDIRECT para localizar a seção redirection, e aprender mais ...

Uma versão online está aqui: 3,6 redirecionamentos

PS:

Muitas vezes, man foi a poderosa ferramenta para aprender Linux.

0 para a entrada, uma de saída padrão e 2 para stderr.

Uma Dica : somecmd >1.txt 2>&1 está correta, enquanto somecmd 2>&1 >1.txt é totalmente errado sem efeito!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top