przekierowanie do / dev / null

144

Czytam przykładowy skrypt powłoki 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

Próbuję zrozumieć użycie „/ dev / null 2> & 1” tutaj. Na początku myślałem, że ten skrypt używa / dev / null, aby z wdziękiem ignorować błędy bez powodowania awarii skryptu (coś w rodzaju próby obsługi wyjątków w językach programowania). Ponieważ nie widzę, jak użycie tar do skompresowania katalogu do pliku tar może spowodować jakiekolwiek błędy.

JohnMerlino
źródło
3
Przekierowanie do /dev/nullnie zapobiegnie awariom, ale wyczyści strumienie wyjściowe stdout i stderr. tarmoże powodować błędy na różne sposoby. Być może nie masz dostępu do zapisu, plik może już istnieć itp.
Sparhawk
3
Tylko sztuczka, aby uniknąć niepotrzebnego wyjścia. Co do tego, dlaczego tar może powodować błędy: ponieważ katalog docelowy nie istnieje, ponieważ źródło nie, ponieważ nie masz dostępu do zapisu do celu lub odczytu do źródła, ponieważ tarnie ma go w $ PATH, ponieważ tarzawiesił się (nigdy nie wiadomo), ponieważ na urządzeniu nie ma już miejsca, ponieważ tarwersja uległa zmianie i teraz wymaga innej składni, ponieważ dysk spowodował błąd we / wy. Jestem pewien, że możesz znaleźć więcej.
terdon

Odpowiedzi:

223

Nie, nie zapobiegnie to awarii skryptu. Jeśli wystąpią jakiekolwiek błędy w tarprocesie (np .: odmowa uprawnień, brak pliku lub katalogu, ...) skrypt nadal się zawiesi.

Ponieważ użycie > /dev/null 2>&1przekieruje wszystkie dane wyjściowe polecenia (zarówno stdouti stderr) /dev/null, co oznacza, że ​​żadne dane wyjściowe nie są drukowane na terminalu.

Domyślnie:

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

W skrypcie używasz > /dev/nullpowodując:

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

A następnie 2>&1powodując:

stdin  ==> fd 0
stdout ==> /dev/null
stderr ==> stdout
Cuonglm
źródło
3
Dla zrozumienia > /dev/null 2>&1, to polecenie powoduje stderr ==> stdout, więc stderr nadal jest drukowany na standardowe wyjście?
Weishi Zeng
11
prawdopodobnie nie za ważne, ale co to jest fd?
kev
7
Dlaczego: CMD > /dev/null 2>&1działa, ale CMD 2>&1 > /dev/nullwciąż daje mi STDERR?
dbmikus
3
Zalecane: użyj 2>& 1w przykładach kodu, aby podkreślić, że liczba i znak & są uważane za część operatora przekierowania. Przekierowanie do pliku często ma miejsce pomiędzy, >a /path/to/fileprzekierowanie do deskryptora pliku jest zasadniczo takie samo.
Henk Langeveld
21

Próbuję zrozumieć użycie „> / dev / null 2> & 1” tutaj.

(zwróć uwagę, że /dev/nullw pytaniu dodałem przekierowanie ).

Powyższe przekieruje STDOUTi STDERRdo /dev/null. Działa poprzez połączenie STDERRz STDOUT. (Zasadniczo wszystkie dane wyjściowe polecenia zostaną przekierowane do urządzenia zerowego .)

... bez powodowania awarii skryptu (coś w rodzaju próby złapania obsługi wyjątków w językach programowania).

To nie do końca tak try/catch. To po prostu wycisza każdy wynik (w tym błąd) z polecenia.

Ponieważ nie widzę, jak użycie tar do skompresowania katalogu do pliku tar może spowodować jakiekolwiek błędy.

Może to powodować błędy z wielu powodów, w tym:

  • Niewystarczające uprawnienia do pliku (ów), które próbujesz zarchiwizować lub do pliku, do którego próbujesz zapisać
  • Brak miejsca na dysku w celu utworzenia archiwum
diabelnie
źródło
dobrze wyjaśnione.
Aditya Gupta
7

Po uruchomieniu CMD> / dev / null 2> i 1

STDOUT przekierowuje na / dev / null, a następnie STDERR przekierowuje na ADRES STDOUT, który został ustawiony na / dev / null, w związku z czym zarówno STDOUT, jak i STDERR wskazują na / dev / null

Przeciwnie, po uruchomieniu CMD 2> i 1> / dev / null

STDERR przekierowuje na ADRES STDOUT (deskryptor pliku 1 w tym momencie lub / proc / self / fd / 1), a następnie STDOUT przekierowuje do / dev / null, ale STDERR ciągle przekierowuje do fd1 !! W rezultacie normalne wyjście z STDOUT jest odrzucane, ale błędy pochodzące z STDERR są nadal zapisywane na konsoli.

zabijaka
źródło
-2

Przekierowanie We / Wy Bash

Główną ideą wyjaśnienia tego jest:

Przekierowania są stosowane od PRAWEJ do LEWEJ, w przeciwieństwie do normalnego sposobu czytania przez anglojęzycznych.


Więc ten kod:

command > filename 2>&1

przekierowuje stderrdo stdout najpierw ( 2>&1), a następnie wysyła stdout(łącznie z przekierowanym stderr) do filename( > filename). Oto wyjaśnienie ABSG (rozdz. 20) .

Ten kod:

command >>/dev/null 2>&1

przekierowuje stderri stdoutdo /dev/null... co oznacza donikąd . Przesyłane rzeczy /dev/nullnie są w żaden sposób zapisywane, buforowane ani zapamiętywane.

Są po prostu wysyłani do „ nigdzie ” i zapominani. Jest to sposób uruchamiania programów i upewnienia się, że nie generują one żadnych danych wyjściowych i nigdy nie będą widoczne w wierszu poleceń ani w pliku dziennika.


Widzę tego typu pytania dość często ... głównie dlatego, że musiałem to sprawdzić sam, ponieważ nie kodowałem od lat. Oto kilka przydatnych informacji z ABSG:

„Przekierowanie oznacza po prostu przechwytywanie danych wyjściowych z pliku, polecenia, programu lub skryptu i wysyłanie go jako danych wejściowych do innego pliku, polecenia, programu lub skryptu”.

2>&1 
# Redirects stderr to stdout.

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

ABSG: Advanced Bash Scripting Guide: Rozdział 20 Powyższy link jest link do przekierowania strony I / O z open source tldp.org dokumentu o nazwie Zaawansowane Bash Scripting Guide przez Mendla Coopera. Jest wymieniony jako „Dogłębna eksploracja sztuki skryptowania powłoki” i całkowicie się zgadzam. Jest to wspaniały zasób i ma mnóstwo odpowiedzi na wszelkiego rodzaju szalone sytuacje.

Inne cenne zasoby: W bieżącej / utrzymywanej sekcji znajduje się wiele cennych zasobów (w kilku przydatnych formatach, takich jak HTML, PDF, tekst itp.) Na stronie Przewodniki po dokumentacji dokumentacji systemu Linux . Oto kilka, które uważam za przydatne:

Sceptycal
źródło
1
Nie, przekierowania są obsługiwane od lewej do prawej. W twoim przykładzie standardowe wyjście jest przekierowywane filename, a następnie standardowy błąd jest przekierowywany do każdego miejsca, w którym obecnie standardowe wyjście jest (do filename). Gdyby było odwrotnie, błąd standardowy kończyłby się na terminalu, podczas gdy przekierowywano tylko standardowe wyjście filename. Ponadto, w command >file1 2>file2, file2nie zostałby utworzony, gdyby file1nie można go było utworzyć (bez względu na to, czy file1i file2faktycznie były to zupełnie inne ścieżki).
Kusalananda