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?


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)

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;

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


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!


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

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.