Enquanto usa o nohup para colocar um comando para executar em segundo plano, alguns conteúdos aparecem no terminal.
cp: error reading ‘/mnt/tt/file.txt’: Input/output error
cp: failed to extend ‘/mnt/tt/file.txt’: Input/output error
Eu quero guardar esse conteúdo num ficheiro.
Há 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 com erro padrão. O operador de redirecionamento clássico (command > file
) apenas redireciona a saída padrão, assim o erro padrão ainda é mostrado no terminal. Para redirecionar a stderr também, você tem algumas opções:
Redirecionar stdout para um arquivo e stderr para outro arquivo:
comando > fora 2> erro
Redirecionar stdout para um arquivo (>out
), e então redirecionar stderr para stdout (2>&1
):
comando >fora 2>&1
Redirecione ambos para um arquivo (este é't suportado por todos os shells, bash
e zsh
suportam-no, por exemplo, mas sh
e ksh
não suportam):
comando &> fora
Para mais informações sobre os vários operadores de controle e redirecionamento, consulte aqui.
A primeira coisa a notar é que existem's duas maneiras dependendo do seu propósito e da sua concha, portanto isto requer uma ligeira compreensão de múltiplos aspectos. Adicionalmente, certos comandos como time
e strace
escrevem output para stderr por padrão, e podem ou não fornecer um método de redirecionamento específico para aquele comando
A teoria básica por trás do redirecionamento é que um processo gerado pela shell (assumindo que é um comando externo e não um shell embutido) é criado via fork()
e execve()
syscalls, e antes que isso aconteça outra chamada ao syscall dup2()
executa os redirecionamentos necessários antes que execve()
aconteça. Nesse sentido, os redirecionamentos são herdados do shell pai. Os m&>n
e m>n.txt
informam a 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 faz & significa exatamente no redirecionamento de saída )
O mais típico, é via 2>
em Bourne-like shells, como dash
(que é ligado simbolicamente a /bin/sh
) e bash
; primeiro é o shell padrão e compatível com POSIX e o outro é o que a maioria dos usuários utilizam para a sessão interativa. Eles diferem em sintaxe e características, mas felizmente para nós o redirecionamento do fluxo de erros funciona da mesma forma (exceto o &>
não padrão). No caso do csh e suas derivadas, o redirecionamento stderr doesn't quite trabalha lá.
Let's voltam a 2>
part. 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 seção 2.7:
[n]redir-op word
Para um simples >
redirecionamento, o 1
inteiro está implícito para stdout
, ou seja, echo Hello World > /dev/null
é exatamente o mesmo que echo Hello World 1>/dev/null
. Note que o número inteiro ou operador de redirecionamento não pode ser citado, caso contrário a shell não'não os reconhece como tal e, em vez disso, trata-os como uma string literal de texto. Quanto ao espaçamento, é importante que o inteiro esteja ao lado do operador de redirecionamento, mas o arquivo pode ou não estar ao lado do operador de redirecionamento, ou seja, command 2>/dev/null
e command 2> /dev/null
funcionarão bem.
A sintaxe um pouco simplificada para o comando típico na shell seria
command [arg1] [arg2] 2> /dev/null
O truque aqui é que o redirecionamento pode aparecer em qualquer lugar. Isso é tanto 2> comando [arg1]
como comando 2> [arg1]
são válidos. Note que para a shell bash', existe
&>maneira de redirecionar ambos os streams stdout e stderr ao mesmo tempo, mas novamente - it's bash specific e se você're esforça-se para a portabilidade dos scripts, pode não funcionar. Veja também [Ubuntu Wiki][8] e [Qual é a diferença entre &> e 2>&1][9]. *Note:* O operador de redirecionamento
>truncata* um arquivo e o sobrescreve, se o arquivo existir. O
2>>pode ser utilizado para anexar
stderrao arquivo. Se você puder notar,
>é destinado 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 redirecionar o fluxo para toda a sessão shell, por assim dizer, seja interativamente ou via script. Algo como
#!/bin/sh
exec 2> ./my_log_file.txt
stat /etc/non_existing_file
Neste exemplo, o arquivo de log deve mostrar stat: cannot stat '/etc/non_existing_file': Não há tal arquivo ou diretório
.
Ainda outra forma é através de funções. Como kopciuszek notado 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 como time
e strace
escrevem sua saída para stderr por padrão. No caso do comando time
, a única alternativa viável é redirecionar a saída de todo o comando , ou seja
time echo foo 2>&1 > file.txt
alternativamente, a lista síncrona ou a sub-capa pode ser redirecionada se você quiser separar a saída ( como mostrado em post relacionado ):
{ time sleep 1 2> sleep.stderr ; } 2> time.txt
Outros comandos, tais como strace
ou dialog
fornecem meios para redirecionar a stderr. A opção strace
tem -o <filename.txt>
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 sub-processo que a strace
vê. O comando dialog
escreve a interface do usuário de texto para stdout mas sai para stderr, então para salvar sua saída para 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á a bandeira --output-fd', que também podemos utilizar. Lá's também existe o método dos tubos nomeados. Eu recomendo a leitura do post vinculado sobre o comando
dialog` para uma descrição completa do que's está acontecendo.