Jak przekierować stderr i stdout do różnych plików, a także wyświetlać je w terminalu?

30

Chcę zobaczyć wynik polecenia w terminalu, jak gdyby nie było przekierowania. Ponadto stderr musi zostać przekierowany do err.log, a stdout musi zostać przekierowany do stdout.log.

Byłoby miło mieć również dokładną kopię tego, co jest wyświetlane w terminalu, tj. Błędy drukowane jako i kiedy występują, w osobnym pliku: stdouterr.log.

balki
źródło
@Nuno Nie, to nie jest. OP chce mieć różne pliki dla stdout i stderr.
dogbane
@dogbane Tak, masz rację. Przepraszam za to.
Nuno C. Inácio,
Wciąż uważam to pytanie za bardzo znajome. Spójrzmy w górę ... Oto bardzo podobny unix.stackexchange.com/q/4195/250 , a oto pokrewny unix.stackexchange.com/q/1416/250
phunehehe

Odpowiedzi:

37

Użyj teepolecenia w następujący sposób:

(cmd | tee stdout.log) 3>&1 1>&2 2>&3 | tee stderr.log

3>&1 1>&2 2>&3 jest jak zamieniasz stderr i stdout, ponieważ tee może zaakceptować tylko stdout.

Spójrz na uniksowe polecenie tee, aby uzyskać bardziej zaawansowane przekierowania tee.

dogbane
źródło
fajne rozwiązanie. Czy jest jakiś sposób na uzyskanie kodu wyjścia cmd?
turbanoff,
2
@turbanoff Wymień cmdz (cmd ; echo >exit_code.txt $?).
Parthian Shot
Uważam, że to powinno lepiej zachować kolejność rzeczy wypisywanych do wiersza poleceń:((cmd | tee stdout.log) 3>&1 1>&2 2>&3 | tee stderr.log)
TTT,
5

Myślę, że zalogowanie stdout i stderr do dwóch różnych plików to świetny pomysł. Czy to nie czyni dzienników asynchronicznymi? Więc wypróbowałem następujące:

  • stdout do „stdout.log” (zgodnie z sugestią dogbane)
  • stderror do „stderr.log” (jak sugeruje dogbane)
  • wszystkie dane wyjściowe do „all.log” i
  • nadal mogę zobaczyć dane wyjściowe na wyświetlaczu (choć w osobnym terminalu!)

((cmd | tee stdout.log) 3>&1 1>&2 2>&3 | tee stderr.log) &> all.log

w innym terminalu

tail -f --sleep-interval=2 all.log
Sreeni
źródło
Czy nie jest możliwe skierowanie stderr bezpośrednio do drugiego tty? W takim przypadku nie jest wymagany plik dziennika.
Steven Lu
@StevenLu tak, jeśli znasz nazwę i masz pozwolenie na napisanie do drugiego tty, które można zrobić.
Jasen
1
łatwiej byłoby &| tee all.logna końcu polecenia zamiast&> all.log
Jasen
@Jasen: 2. raz widzę &|. Rozumiem &>, |&też, ale co to &|znaczy w tym kontekście? Nie mogłem znaleźć odpowiedniego odwołania do składni, nie w sieci, nawet nie przeglądając strony podręcznika bash „bash (1)” ... Tx
Cbhihe
1
@Chihihe, o ile mogę powiedzieć, że nic nie robi, chciałem powiedzieć|&
Jasen
3

@dogbane, Thanks.
Znalazłem też inny sposób, który zapisuje oba strumienie w przybliżeniu w kolejności, w jakiej byłyby drukowane bez przekierowania.

command 2> >(tee errlog | tee -a bothLog > /dev/tty ) | tee outlog | tee -a bothLog

Ale działa to tylko z powłokami, które obsługują podstawianie procesów.

balki
źródło
-2

Spróbuj tego :

command 2>&1 | tee bothLog
wazelina
źródło
4
Witaj vasile, to nie odpowiada na pytanie: balki potrzebuje osobnych plików dla stdout i stderr, twoje rozwiązanie miksowałoby oba w tym samym strumieniu.
Mat.
Dlaczego ludzie łączą stdout i stderr razem? Lub powiedz innym, żeby to zrobili?
nurettin