Jak za pomocą basha przesłać błąd standardowy do innego procesu?

137

Powszechnie wiadomo, jak przełączyć standardowe wyjście procesu na standardowe wejście innego procesu:

proc1 | proc2

Ale co, jeśli chcę wysłać błąd standardowy proc1 do proc2 i pozostawić standardowe wyjście w jego bieżącej lokalizacji? Można by pomyśleć, że bashmiałoby polecenie w stylu:

proc1 2| proc2

Ale niestety nie. Czy jest na to sposób?

paxdiablo
źródło
Możesz zrobić takie proste przekierowanie w rc, w którym jest inna powłoka. Np proc1 |[2] proc2. : . Czy to nie miłe? bashAle nie w środku.
Rolf

Odpowiedzi:

168

Istnieje również substytucja procesu . Co sprawia, że ​​proces zastępuje plik.
Możesz wysłać stderrdo pliku w następujący sposób:

process1 2> file

Ale możesz podstawić proces dla pliku w następujący sposób:

process1 2> >(process2)

Oto konkretny przykład, który wysyła stderrzarówno na ekran, jak i dołącza do pliku dziennika

sh myscript 2> >(tee -a errlog)
Szkot
źródło
23
To poprawnie odpowiada na postawione pytanie i powinno być zaakceptowaną odpowiedzią przez @paxdiablo
mmlb.
Próbowałem tego. To nie zadziałało ( weston --help 2> >(less)) i zepsuło mi skorupę, musiałem wyjść i zalogować się ponownie.
Rolf
1
@Rolf, jeśli obaj weston --helpi lessspodziewają się interakcji z klawiaturą, ale tylko 1 z nich ją otrzyma, możesz być w niezręcznej sytuacji. grepZamiast tego spróbuj przeprowadzić testy za pomocą czegoś takiego . Dodatkowo może się okazać, że oba wejścia myszy / klawiatury i tak przechodzą do drugiego polecenia, a nie do westona.
BeowulfNode42
88

Możesz użyć następującej sztuczki, aby zamienić stdout i stderr. Następnie wystarczy użyć zwykłej funkcji potoku.

( proc1 3>&1 1>&2- 2>&3- ) | proc2

Pod warunkiem, stdouti stderrzarówno wskazał tym samym miejscu na początku, to da ci to, czego potrzebujesz.

To, co x>yrobi bit, to zmiana uchwytu pliku, xwięc wysyła teraz informacje do miejsca, w którym uchwyt pliku ywskazuje. W naszym konkretnym przypadku:

  • 3>&1tworzy nowy uchwyt, 3który będzie wyprowadzany do bieżącego uchwytu 1(oryginalne standardowe wyjście), tylko po to, aby zapisać go gdzieś na ostatni punkt poniżej.
  • 1>&2modyfikuje uchwyt 1(stdout), aby wyprowadzał do bieżącego uchwytu 2(oryginalny stderr).
  • 2>&3-modyfikuje uchwyt 2(stderr), aby wyprowadzał do bieżącego uchwytu 3(oryginalne standardowe wyjście), a następnie zamyka uchwyt 3(przez -na końcu).

W rzeczywistości jest to polecenie swap, które widzisz w algorytmach sortowania:

temp   = value1;
value1 = value2;
value2 = temp;
paxdiablo
źródło
3
Jaka jest wartość używania 1>&2-tutaj, a nie tylko 1>&2? Nie rozumiem, dlaczego chcielibyśmy zamknąć fd 2, jeśli zamierzamy go natychmiast ponownie otworzyć / przypisać.
wątpliwyjim
1
@dubiousjim, bez korzyści w tym konkretnym przypadku, podejrzewam, że zrobiłem to tylko po to, aby być konsekwentnym - uchwyt zamykający plik 3 jest dobrym pomysłem, aby go zwolnić.
paxdiablo
Słuszna uwaga, @ovgolovin, nie mogę uwierzyć, że nikt nie odebrał tego w ciągu siedmiu miesięcy, odkąd dokonałem tej edycji. Naprawiono zgodnie z twoją sugestią.
paxdiablo
próbuję zmusić markę gcc (która jest pokolorowana w moim systemie) do pracy z tym "(make 3> & 1 1> & 2- 2> & 3-) | less -R" gdzie "(ls -al 3> & 1 1> & 2- 2> & 3-) | less -R "działa zgodnie z oczekiwaniami.
niezsynchronizowane
Wygląda na to, że Twoje wyjaśnienia dotyczą dwóch drugich przekierowań. 1> & 2- ustawia uchwyt pliku 2 (oryginalny stderr) na uchwyt 1 (oryginalne standardowe wyjście) 2> & 3 ustawia uchwyt pliku 3 (skopiowane standardowe wyjście) na uchwyt 2 (oryginalny stderr). Proszę, popraw mnie, jeśli się mylę. btw, zgaduję, że myślnik na 2 ma zapobiec wysyłaniu nowych danych stderr do tego bufora, gdy jest on zapełniany danymi ze standardowego wyjścia.
aghsmith
70

Bash 4 ma tę funkcję:

Jeśli używane jest `| & ', standardowy błąd polecenia1 jest łączony ze standardowym wejściem polecenia2 przez potok; jest to skrót od 2> & 1 |. To niejawne przekierowanie standardowego błędu jest wykonywane po wszelkich przekierowaniach określonych przez polecenie.

zsh ma również tę funkcję.

-

W przypadku innych / starszych powłok, po prostu wprowadź to wyraźnie jako

FirstCommand 2> & 1 | OtherCommand

Wstrzymano do odwołania.
źródło
14
Czytając dokumentację, powoduje to zarówno standardowy błąd, jak i wyjście, w przeciwieństwie do zwykłego standardowego błędu , ale dobrze jest wiedzieć. Myślę, że czas zacząć przyglądać się bash 4.
paxdiablo
Bieżący podręcznik basha czyta "Jeśli używany jest | &, standardowy błąd polecenia, oprócz standardowego wyjścia, jest podłączony do standardowego wejścia polecenia2". To wyraźnie nie jest to, czego chce PO.
Peter - Przywróć Monikę
@ PeterA.Schneider: OP mówi „zostaw standardowe wyjście w jego bieżącej lokalizacji”, co może być niejednoznaczne.
Wstrzymano do odwołania.
Nie widzę żadnej dwuznaczności. Twoja sugestia (1) łączy te dwa strumienie. (2) OtherCommandzapisuje połączone dane gdzieś, prawdopodobnie gdzie indziej. Więc to nie są te same dane i potencjalnie są przenoszone gdzie indziej. To jest przeciwieństwo życzenia PO, prawda?
Peter - Przywróć Monikę
@ PeterA.Schneider: Gdzie jeszcze znajduje się bieżąca lokalizacja standardowego wyjścia? Jeśli proc1wyjście na stdout i na stderr i chcesz, aby stderr przeszedł do stdin proc2(czyli tam, gdzie zmierza stdout proc1), wtedy moja odpowiedź to robi. Dałem OP to, o co prosił , a może nie to, o co chciał poprosić. Na tym polega potencjalna dwuznaczność. OP przyjął odpowiedź, która zamienia stdout i stderr, co nie jest tym, o co prosił.
Wstrzymano do odwołania.
27

Zamiana jest świetna, ponieważ rozwiązuje problem. Na wypadek, gdybyś nie potrzebował nawet oryginalnego standardowego wyjścia, możesz to zrobić w ten sposób:

proc1 2>&1 1>/dev/null | proc2

Porządek jest niezbędny; nie chciałbyś:

proc1 >/dev/null 2>&1 | proc1

Ponieważ to przekieruje wszystko do /dev/null!

kccqzy
źródło
0

Żaden z nich nie działał naprawdę dobrze. Najlepszy sposób, w jaki znalazłem robienie tego, co chciałeś, to:

(command < input > output) 2>&1 | less

Działa to tylko w przypadkach, w których commandnie jest wymagane wprowadzanie danych z klawiatury. na przykład:

(gzip -d < file.gz > file) 2>&1 | less

umieściłby błędy gzip w less

sbingner
źródło