redirecionando para / dev / null

144

Estou lendo um exemplo de script do shell bash:

#!/bin/bash

# This script makes a backup of my home directory.

cd /home

# This creates the archive
tar cf /var/tmp/home_franky.tar franky > /dev/null 2>&1

# First remove the old bzip2 file.  Redirect errors because this generates some if the archive
# does not exist.  Then create a new compressed file.
rm /var/tmp/home_franky.tar.bz2 2> /dev/null
bzip2 /var/tmp/home_franky.tar

# Copy the file to another host - we have ssh keys for making this work without intervention.
scp /var/tmp/home_franky.tar.bz2 bordeaux:/opt/backup/franky > /dev/null 2>&1

# Create a timestamp in a logfile.
date >> /home/franky/log/home_backup.log
echo backup succeeded >> /home/franky/log/home_backup.log

Estou tentando entender o uso de "/ dev / null 2> & 1" aqui. No começo, pensei que esse script usasse / dev / null para ignorar os erros normalmente, sem causar a falha do script (como tentar pegar o tratamento de exceções nas linguagens de programação). Porque não vejo como o uso do tar para compactar um diretório em um arquivo tar poderia causar qualquer tipo de erro.

JohnMerlino
fonte
3
Redirecionar para /dev/nullnão evitará falhas, mas limpará os fluxos de saída stdout e stderr. tarpode causar erros de várias maneiras. Você pode não ter acesso de gravação, o arquivo já pode existir etc.
Sparhawk:
3
Apenas um truque para evitar saída desnecessária. Por que o tar pode causar erros: porque o diretório de destino não existe, porque a fonte não existe, porque você não tem acesso de gravação ao destino ou lê na fonte, porque tarnão está no seu $ PATH, porque tartravou (você nunca sabe), porque não há espaço no dispositivo, porque a tarversão mudou e agora requer sintaxe diferente, porque o disco causou um erro de E / S. Tenho certeza que você pode encontrar mais.
terdon

Respostas:

223

Não, isso não impedirá que o script falhe. Se ocorrer algum erro no tarprocesso (por exemplo: permissão negada, nenhum arquivo ou diretório, ...), o script ainda falhará.

Como o uso > /dev/null 2>&1redirecionará toda a sua saída de comando (ambos stdoute stderr) para /dev/null, o que significa que nenhuma saída é impressa no terminal.

Por padrão:

stdin  ==> fd 0
stdout ==> fd 1
stderr ==> fd 2

No script, você usa > /dev/nullcausando:

stdin  ==> fd 0
stdout ==> /dev/null
stderr ==> fd 2

E então 2>&1causando:

stdin  ==> fd 0
stdout ==> /dev/null
stderr ==> stdout
cuonglm
fonte
3
Pelo que entendi > /dev/null 2>&1, esse comando resulta em stderr ==> stdout, então o stderr ainda é impresso em stdout ??
amigos estão dizendo sobre
11
provavelmente não é muito importante, mas o que é fd?
kev
7
Por que: CMD > /dev/null 2>&1funciona, mas CMD 2>&1 > /dev/nullainda me dá STDERR?
dbmikus
3
Recomendado: use 2>& 1em exemplos de código para enfatizar que o número e oe comercial são considerados parte do operador de redirecionamento. É comum que o redirecionamento para um arquivo tenha um espaço entre >e /path/to/file, o redirecionamento para um descritor de arquivo é essencialmente a mesma coisa.
Henk Langeveld
21

Estou tentando entender o uso de "> / dev / null 2> & 1" aqui.

(observe que eu adicionei o redirecionamento antes /dev/nullna sua pergunta.)

O acima redirecionaria o STDOUTe STDERRpara /dev/null. Ele funciona mesclando o STDERRno STDOUT. (Essencialmente, toda a saída do comando seria redirecionada para o dispositivo nulo .)

... sem causar a falha do script (como tentar detectar o tratamento de exceções nas linguagens de programação).

Não é bem assim try/catchou algo assim. Ele simplesmente silencia qualquer tipo de saída (incluindo erro) do comando.

Porque não vejo como o uso do tar para compactar um diretório em um arquivo tar poderia causar qualquer tipo de erro.

Isso pode resultar em erros por vários motivos, incluindo:

  • Permissões inadequadas nos arquivos para os quais você está tentando arquivar ou nos quais você está tentando gravar
  • Falta de espaço em disco para criar o arquivo
devnull
fonte
bem explicado.
Aditya Gupta
7

Quando você executa o CMD> / dev / null 2> & 1

STDOUT redireciona para / dev / null e, em seguida, STDERR redireciona para THE ADDRESS of STDOUT, que foi definido como / dev / null, consequentemente, STDOUT e STDERR apontam para / dev / null

Por outro lado, quando você executa o CMD 2> & 1> / dev / null

O STDERR redireciona para O ENDEREÇO ​​do STDOUT (descritor de arquivo 1 naquele momento, ou / proc / self / fd / 1) e, em seguida, o STDOUT redireciona para / dev / null, mas o STDERR continua redirecionando para o fd1 !! Como resultado, a saída normal do STDOUT é descartada, mas os erros provenientes do STDERR ainda estão sendo gravados no console.

Hector
fonte
-2

Redirecionamento de E / S do Bash

A principal idéia para esclarecer as coisas é esta:

Os redirecionamentos são aplicados de DIREITA para ESQUERDA, ao contrário do que os falantes de inglês normalmente lêem.


Portanto, este código:

command > filename 2>&1

redireciona stderrpara stdout first ( 2>&1) e depois envia stdout(incluindo o redirecionado stderr) para filename( > filename). Aqui está a explicação do ABSG (cap. 20) .

Este código:

command >>/dev/null 2>&1

redireciona stderre stdoutpara /dev/null... o que significa para lugar nenhum . As coisas enviadas para /dev/nullnão são salvas, armazenadas em cache ou lembradas de forma alguma.

Eles são apenas enviados para ' lugar nenhum ' e esquecidos. Essa é uma maneira de executar programas e garantir que eles produzam saída NO e nunca sejam vistos na linha de comando ou em um arquivo de log.


Eu vejo esse tipo de pergunta um pouco ... principalmente porque eu tive que procurar por mim mesmo desde que eu não codigo há anos. Aqui estão algumas informações úteis do ABSG:

"Redirecionar simplesmente significa capturar a saída de um arquivo, comando, programa ou script e enviá-la como entrada para outro arquivo, comando, programa ou script".

2>&1 
# Redirects stderr to stdout.

command >>filename 2>&1
# Appends both stdout and stderr
#+  to the file "filename" ...

ABSG: Advanced Bash Scripting Guide: O link do Capítulo 20 acima é um link para a página de redirecionamento de E / S do documento de código-fonte aberto tldp.org chamado Advanced Bash Scripting Guide de Mendel Cooper. Ele está listado como "Uma exploração aprofundada da arte do script de shell" e concordo plenamente. É um recurso fantástico e tem toneladas de respostas para todos os tipos de situações malucas.

Outros recursos valiosos: Existem muitos recursos valiosos na seção atual / mantida (em vários formatos úteis, como html, pdf, texto, etc.) na página Guias de projeto de documentação do Linux . Aqui estão alguns que eu achei úteis:

Skeptycal
fonte
1
Não, os redirecionamentos são manipulados da esquerda para a direita. No seu exemplo, a saída padrão é redirecionada para filename, e o erro padrão é redirecionado para onde quer que a saída padrão esteja indo atualmente (para filename). Se fosse o contrário, o erro padrão terminaria no terminal enquanto apenas a saída padrão fosse redirecionada filename. Além disso, em command >file1 2>file2, file2não seria criado se file1não pudesse ser criado (não importa se file1e file2eram realmente nomes de caminho totalmente diferentes).
Kusalananda