Como redirecionar stderr para um arquivo

Ao usar o nohup para colocar um comando para executar em segundo plano, parte do conteúdo aparece no terminal.

cp: error reading ‘/mnt/tt/file.txt’: Input/output errorcp: failed to extend ‘/mnt/tt/file.txt’: Input/output error

Quero salvar esse conteúdo em um arquivo.

Existem dois fluxos de saída principais no Linux (e outros sistemas operacionais), saída padrão (stdout) e erro padrão (stderr). As mensagens de erro, como as que você mostra, são impressas como erro padrão. O operador de redirecionamento clássico (command > file) apenas redireciona a saída padrão, portanto, o erro padrão ainda é mostrado no terminal. Para redirecionar stderr também, você tem algumas opções:

  1. Redirecionar stdout para um arquivo e stderr para outro arquivo:

    command > out 2>error
  2. Redirecionar stdout para um arquivo (>out), e então redirecionar stderr para stdout (2>&1):

    command >out 2>&1
  3. Redirecione ambos para um arquivo (isso não é suportado por todos os shells, bash e zsh apoiá - lo, por exemplo, mas sh e ksh nao):

    command &> out

Para obter mais informações sobre os vários operadores de controle e redirecionamento, consulte aqui.

A primeira coisa a notar é que há algumas maneiras dependendo do seu propósito e shell, portanto, isso requer uma leve compreensão de vários aspectos. Além disso, certos comandos, como time e strace escreva a saída para stderr por padrão e pode ou não fornecer um método de redirecionamento específico para esse comando

A teoria básica por trás do redirecionamento é que um processo gerado pelo shell (assumindo que é um comando externo e não o shell embutido) é criado via fork() e execve() syscalls, e antes que isso aconteça outra syscall dup2() executa redirecionamentos necessários antes execve() acontecer. Nesse sentido, os redirecionamentos são herdados do shell pai. O m&>n e m>n.txt informe o shell sobre como executar open() e dup2() syscall (veja também Como funciona o redirecionamento de entrada, Qual é a diferença entre redirecionamento e pipe, e O que significa & amp; exatamente no redirecionamento de saída )

Redirecionamentos Shell

Mais típico, é via 2> em Conchas semelhantes a Bourne, como dash (que tem um link simbólico para /bin/sh) e bash; primeiro é o shell padrão e compatível com POSIX e o outro é o que a maioria dos usuários usa para sessão interativa. Eles diferem em sintaxe e recursos, mas felizmente para nós o redirecionamento de fluxo de erro funciona da mesma forma (exceto o &> não padrão). No caso de csh e seus derivados, o redirecionamento stderr não funciona bem lá.

Vamos voltar para 2> parte. Duas coisas importantes a notar: > significa operador de redirecionamento, onde abrimos um arquivo e 2 integer significa descritor de arquivo stderr; na verdade, é exatamente assim que o padrão POSIX para linguagem shell define o redirecionamento em secção 2.7:

[n]redir-op word

Para simples > redirecionamento, o 1 inteiro está implícito para stdout, seja. echo Hello World > /dev/null é o mesmo que echo Hello World 1>/dev/null. Observe que o operador inteiro ou de redirecionamento não pode ser citado, caso contrário, o shell não os reconhece como tal e, em vez disso, trata como uma string literal de texto. Quanto ao espaçamento, é importante que integer esteja ao lado do operador de redirecionamento, mas file pode estar ao lado do operador de redirecionamento ou não, ou seja. command 2>/dev/null e command 2> /dev/null vai funcionar muito bem.

A sintaxe um tanto simplificada para o comando típico no shell seria

 command [arg1] [arg2]  2> /dev/null

O truque aqui é que o redirecionamento pode aparecer em qualquer lugar. Isso é ambos 2> command [arg1] e command 2> [arg1] são válidos. Observe que para bash shell, lá existe &> maneira de redirecionar os fluxos stdout e stderr ao mesmo tempo, mas novamente - é específico do bash e se você está se esforçando para a portabilidade de scripts, pode não funcionar. Ver Ubuntu Wiki e >>Qual é a diferença entre & E 2 & amp;1.

Notar: O > operador de redirecionamento truncar um arquivo e sobrescreve-lo, se o arquivo existe. O 2>> pode ser usado para anexar stderr arquivar.

Se você pode notar, > destina-se a um único comando. Para scripts, podemos redirecionar o fluxo stderr de todo o script de fora como em myscript.sh 2> /dev/null ou podemos fazer uso de exec built-in. O exec built-in tem o poder de religar o fluxo para toda a sessão shell, por assim dizer, seja interativamente ou via script. Algo como

#!/bin/shexec 2> ./my_log_file.txtstat /etc/non_existing_file

Neste exemplo, o arquivo de log deve mostrar stat: cannot stat '/etc/non_existing_file': No such file or directory.

Ainda outra maneira é através de funções. Como borralheira observado em sua resposta, podemos escrever declaração de função com redirecionamento já anexado, ou seja

some_function(){    command1    command2} 2> my_log_file.txt

Comandos escrevendo para stderr exclusivamente

Comandos como time e strace escreva sua saída para stderr por padrão. Em caso de time comando, a única alternativa viável é redirecionar a saída de todo o comando , ou seja

time echo foo 2>&1 > file.txt

como alternativa, a lista síncrona ou o subshell podem ser redirecionados se você quiser separar a saída ( conforme mostrado em postagem relacionada ):

{ time sleep 1 2> sleep.stderr ; } 2> time.txt

Outros comandos, como strace ou dialog fornecer meios para redirecionar stderr. strace ha -o <filename.txt> opção que permite especificar o nome do arquivo onde a saída deve ser escrita. Há também uma opção para escrever um arquivo de texto para cada subprocesso que strace ver. O dialog o comando grava a interface do usuário de texto em stdout, mas a saída em stderr, portanto, para Salve sua saída em variável ( porque var=$(...) e pipelines só recebe stderr) precisamos trocar os descritores de arquivo

result=$(dialog --inputbox test 0 0 2>&1 1>/dev/tty);

mas, além disso, há --output-fd bandeira, que também podemos utilizar. Há também o método de pipes nomeados. Eu recomendo ler o post vinculado sobre o dialog comando para descrição completa do que está acontecendo.

@ terdon esta é uma pergunta mais específica e aparece corretamente na pesquisa do google para a pergunta mais específica, o que é uma coisa boa.

@ nroose sim, e vai continuar aparecendo, isso não vai mudar. Mas quaisquer novas respostas devem ir para a questão mais geral.