Jak uruchomić polecenie w tle bez wyjścia, chyba że wystąpi błąd

13

Jak ukryć dane wyjściowe polecenia, ale pokazać, czy polecenie kończy kodowanie błędu?

Xster
źródło

Odpowiedzi:

17

Niestety założenie, że stderr jest używany tylko do wyświetlania błędów, nie zawsze jest poprawny. Raczej, stderr jest często używany dla wszystkich interaktywny wyjście i diagnostyka, tj. wyjście przeznaczone dla użytkownika do odczytania w interaktywnym pytaniu 1 . wget i dd są dobrze znane przykłady.

Niektóre polecenia dostarczą flagę (np. -quiet lub -silent ) aby pominąć wyjście bez błędów - przeczytaj strony podręcznika, aby zobaczyć, czy istnieje.


Inną konwencją, która częściej się trzyma, jest konwencja kod wyjścia : program zwraca kod wyjścia, gdy wychodzi. Zazwyczaj 2 , kod wyjścia 0 wskazuje sukces, a każdy inny kod wyjścia wskazuje błąd.

Z bash, możesz uzyskać kod wyjścia ostatniego polecenia z $? zmienna. W fish, Użyj $status zmienna. Możesz fajkować stderr do pliku tymczasowego i wydrukuj go tylko w przypadku wystąpienia błędu. Na przykład ( fish ):

command 2>/tmp/outputbuffer
if $status
    cat /tmp/outputbuffer
rm /tmp/outputbuffer

Możesz także użyć niektórych skrótów, jeśli nie łączysz poleceń:

if command 2>/tmp/outputbuffer
    cat /tmp/outputbuffer
rm /tmp/outputbuffer

Lub:

command 2>/tmp/outputbuffer; or cat /tmp/outputbuffer; rm /tmp/outputbuffer;

Możesz także fajkować stdout do tego samego bufora za pomocą 2>&1 >/tmp/outputbuffer.

(Uwaga: właściwie nie wiem fish, więc dostosowuję koncepcję do tego, co mogę znaleźć w jej dokumentacji. Składnia może być nieco błędna. Możesz także użyć mktemp aby wygenerować unikalny plik tymczasowy - uruchom go i zapisz nazwę pliku w zmiennej.)

Jeśli chcesz uruchomić całą rzecz w tle powłoki, której używasz także interaktywnie w tym samym czasie, lepiej napisać skrypt do obsługi ukrywania wyjścia i uruchamiania tego skryptu w tle za pomocą standardowe techniki ( fish ). Do cholery, możesz umieścić coś w rodzaju następującej funkcji ~/.config/fish/config.fish:

function run-silent
    set temp (mktemp)
    if $argv 2>&1 >$temp
        cat $temp
    rm $temp
end

Zadzwoń z run-silent somecommand & (gdzie trailing & powoduje, że działa w tle)

Zauważ, że spowoduje to połknięcie oryginalnego kodu wyjścia i spowoduje zrzucenie obu stdout i stderr w przypadku awarii. Możesz dostosować go w razie potrzeby.


1 Nie ma nawet gwarancji, że wyjście błędu nie pojawi się stdout - niektóre programy zrzucają tam wszystkie dane wyjściowe!

2 Niestety, nie zawsze tak jest - kod wyjścia jest całkowicie kontrolowany przez program, a niektóre wskazują na pewne warunki sukcesu przy niezerowych wyjściach. Ponownie sprawdź instrukcję.

Bob
źródło
niewielkie ulepszenie ryby, jest specjalne miejsce do umieszczania funkcji w ~ / .config / fish / functions /
Xster
12

Narzędzia uniksowe wysyłają ogólne wiadomości do stdouti komunikaty o błędach do stderr, więc jeśli chcemy tylko wyświetlać komunikaty o błędach, wystarczy je wyłączyć stdout tak tylko stderr dostaje się do konsoli.

Sposób, aby to zrobić (w obu bash i fish ) jest dołączać >/dev/null do polecenia. Rury te przechodzą w nicość, ale stderr (z twoimi komunikatami o błędach) nadal trafia do konsoli.

Na przykład:

Komenda echo 1 >/dev/null nic nie drukuje, ponieważ normalne stdout wyjście jest wyłączone i nic nie zostało zapisane na stderr.

Komenda man doesnotexist >/dev/null drukuje komunikat o błędzie, ponieważ man zapisuje swój komunikat o błędzie do stderr.

Maximillian Laumeister
źródło
2

Spowoduje to uruchomienie polecenia w tle i zapisanie błędów w pliku dziennika, ignorując normalne wyjście

    command > /dev/null 2> /tmp/example_error.log &
Genkus
źródło