Przechwytywanie STDERR i STDOUT do pliku przy użyciu trójnika

16

Nie jestem pewien, jaka jest najlepsza kolejność przechwytywania zarówno do, jak STDERRi STDOUTdo tego samego pliku za pomocą tee. Wiem, że jeśli chcę potokować do pliku, muszę mapować uchwyt pliku po przekierowaniu, tj

find . >/tmp/output.txt 2>&1

To instruuje powłokę, aby wysłać STDOUTdo, /tmp/output.txta następnie wysłać STDERRdo STDOUT(który teraz wysyła do /tmp/output.txt).

Próba wykonania 2>&1przed przekierowaniem pliku nie przyniesie pożądanego efektu.

Jednak gdy chcę używać potoku, teepowinno to być:

find . |tee /tmp/output.txt 2>&1   # or
find . 2>&1 |tee /tmp/output.txt   # ?
PP.
źródło

Odpowiedzi:

19

Ten ostatni; upewnia się, że STDOUT i STDERR oryginalnego polecenia przechodzą do tego samego fd, a następnie podaje je razem do tee. W pierwszym przypadku jest to STDERR polecenia tee, do którego dołączasz za pomocą STDOUT.

Szalony Kapelusznik
źródło
5
Co ciekawe, strona podręcznika użytkownika bash mówi: „Jeśli |&zostanie użyty, standardowy błąd polecenia 1 jest połączony ze standardowym wejściem polecenia 2 przez potok; jest to skrót 2>&1 |. To niejawne przekierowanie standardowego błędu jest wykonywane po wszelkich przekierowaniach określonych przez polecenie”.
PP.
Musiałem stworzyć mały program C, który pisze zarówno do, jak stderri stdoutdo zrozumienia tego problemu. Operatory przekierowania >i trójnika |różnią się podczas próby przechwycenia obu strumieni wyjściowych. Do przekierowania musiałem ./testapp > /tmp/out.log 2>&1. Natomiast na tee musiałem ./testapp 2>&1 | tee /tmp/out.log.
typelogiczny
@daixtr za to, co jest warte, |zwykle jest określany jako operator potoku. teeodnosi się tylko do konkretnego programu, który jest wywoływany na drugim końcu potoku.
MadHatter