Jak przekierować wyjście dowolnego polecenia?


14

Próbuję napisać prosty skrypt do monitorowania stanu mojej sieci, bez wszystkich danych pingwyjściowych:

ping -q -c 1 google.com > /dev/null && echo online || echo offline

Problem polega na tym, że gdy nie mam połączenia, nadal pojawia się komunikat o błędzie w moich wynikach:

ping: unknown host google.com
offline

Jak mogę ukryć ten komunikat o błędzie poza zasięgiem?

Odpowiedzi:


28

Kiedy biegniesz:

ping -q -c 1 google.com > /dev/null && echo online || echo offline

Jesteś w zasadzie tylko przekierowanie wyjścia strumienia 1 (tj stdout) w celu /dev/null.

Jest to dobre, gdy chcesz przekierować dane wyjściowe, które powstają podczas normalnego wykonywania programu. Jeśli jednak chcesz przekierować dane wyjściowe spowodowane przez wszystkie błędy, ostrzeżenia lub awarie, powinieneś również przekierować stderrstrumień lub Błąd standardowy /dev/null.

Jednym ze sposobów na to jest dodanie numeru strumienia, który chcesz przekierować do operatora przekierowania, na >przykład:Command 2> /dev/null

Dlatego twoje polecenie wyglądałoby następująco:

ping -q -c 1 google.com > /dev/null 2> /dev/null && echo online || echo offline

Zauważ jednak, że przekierowaliśmy już jeden strumień do /dev/null. Dlaczego nie po prostu piggyback na tym samym przekierowaniu? Bash pozwala nam to zrobić, określając numer strumienia, na który należy przekierować. 2>&1.

Zwróć uwagę na &znak po operatorze przekierowania. Mówi to powłoce, że to, co pojawi się później, nie jest nazwą pliku, ale identyfikatorem strumienia wyjściowego.

ping -q -c 1 google.com > /dev/null 2>&1  echo online || echo offline

Uważaj na operatorów przekierowań, ich kolejność ma duże znaczenie. Jeśli przekierujesz w niewłaściwej kolejności, otrzymasz nieoczekiwane wyniki.

Innym sposobem na osiągnięcie całkowitej ciszy jest przekierowanie wszystkich strumieni wyjściowych do /dev/nullkorzystania z tego skrótu: &>/dev/null(lub przekierowanie do pliku dziennika za pomocą &>/path/to/file.log).

Dlatego napisz polecenie jako:

ping -q -c 1 google.com &> /dev/null && echo online || echo offline

1
Aha &>/dev/nullto jest. Dziękujemy wszystkim za natychmiastową pomoc!
operalala

4
Be careful with the redirection operators, their order matters a lot., ale nie podałeś przykładu faktycznego używania2>&1
Izkata

Zapomniałem dodać tego! Edytowana odpowiedź odzwierciedlająca przykład. Kiedy będę miał trochę więcej czasu, wyjaśnię, jak działa porządkowanie.
darnir

9

Musisz przekierować zarówno standardowe wyjście ( >lub 1>), jak i błąd standardowy ( 2>):

ping -q -c 1 google.com > /dev/null 2>/dev/null && echo online || echo offline

lub przekieruj jeden na drugi:

ping -q -c 1 google.com > /dev/null 2>&1 && echo online || echo offline

8
$ ping -q -c 1 google.com > /dev/null 2>&1 && echo online || echo offline

Przykłady

$ ping -q -c 1 google.com > /dev/null 2>&1 && echo online || echo offline
online

$ ping -q -c 1 googleadf.com > /dev/null 2>&1 && echo online || echo offline
offline

Przyspieszenie ping

W zależności od pingimplementacji możesz być ograniczony do jednej liczby -c 1. Niektóre implementacje pozwolą Ci zejść poniżej tego, ale zasadniczo musisz poczekać na przekroczenie limitu czasu złych wyszukiwań. Więc zamiast używać, pingmożesz chcieć użyć fingzamiast tego.

powolność pingowania zawodzącego

$ date; ping -q -c 1 google.com > /dev/null 2>&1 && echo online || echo offline; date
Tue Jan 28 13:51:10 EST 2014
online
Tue Jan 28 13:51:10 EST 2014

$ date; ping -q -c 1 googleadf.com > /dev/null 2>&1 && echo online || echo offline; date
Tue Jan 28 13:51:15 EST 2014
offline
Tue Jan 28 13:51:25 EST 2014

palec jest znacznie szybszy do porażki

$ date; fing -p google.com > /dev/null 2>&1 && echo online || echo offline; date
Tue Jan 28 13:49:21 EST 2014
online
Tue Jan 28 13:49:22 EST 2014

$ date; fing -p googleadf.com > /dev/null 2>&1 && echo online || echo offline; date
Tue Jan 28 13:49:35 EST 2014
online
Tue Jan 28 13:49:38 EST 2014

1
Wolę używać timepolecenia niż ręcznie obliczać różnicę czasu z date:time { fing -p googleadf.com > /dev/null 2>&1 && echo online || echo offline; }
Ruslan

@ Ruslan - dzięki, zrobiłem to w ten sposób b / c chciałem wynik date. IMO łatwiej komuś innemu odczytać wygenerowane dane wyjściowe.
slm
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.