Chcę skonfigurować mój terminal, aby stderr
był drukowany w innym kolorze niż stdout
; może czerwony. Ułatwiłoby to rozróżnienie między nimi.
Czy istnieje sposób, aby to skonfigurować .bashrc
? Jeśli nie, czy to w ogóle możliwe?
Uwaga : To pytanie zostało połączone z innym , o które proszono stderr
, stdout
a echo wejściowe użytkownika ma być wyprowadzane w 3 różnych kolorach . Odpowiedzi mogą dotyczyć obu pytań.
Odpowiedzi:
To jest trudniejsza wersja Pokaż tylko stderr na ekranie, ale zapisz zarówno stdout, jak i stderr do pliku .
Aplikacje działające w terminalu używają jednego kanału do komunikacji z nim; aplikacje mają dwa porty wyjściowe, stdout i stderr, ale oba są podłączone do tego samego kanału.
Możesz podłączyć jeden z nich do innego kanału, dodać kolor do tego kanału i połączyć dwa kanały, ale spowoduje to dwa problemy:
␛[31m
Oznacza „przełącz na czerwony pierwszy plan”. Oznacza to, że jeśli część danych wyjściowych przeznaczonych do wyjścia standardowego pojawi się w momencie wyświetlenia niektórych danych wyjściowych dla standardu wyjściowego, dane wyjściowe będą błędne. (Co gorsza, jeśli w środku sekwencji ucieczki znajduje się przełącznik kanałów, zobaczysz śmieci).Zasadniczo byłoby możliwe napisanie programu, który nasłuchuje na dwóch ptys¹, synchronicznie (tj. Nie przyjmie danych wejściowych na jednym kanale, gdy przetwarza dane wyjściowe na drugim kanale), i natychmiast wyśle dane wyjściowe do terminala z odpowiednimi instrukcjami zmiany kolorów. Straciłbyś możliwość uruchamiania programów, które współdziałają z terminalem. Nie znam żadnej implementacji tej metody.
Innym możliwym podejściem byłoby spowodowanie, aby program wyświetlał prawidłowe sekwencje zmieniające kolory, przechwytując wszystkie funkcje libc, które wywołują wywołanie
write
systemowe w załadowanej biblioteceLD_PRELOAD
. Zobacz odpowiedź chorego na istniejące wdrożenie lub odpowiedź Stéphane Chazelas na mieszane podejście, które wykorzystujestrace
.W praktyce, jeśli ma to zastosowanie, sugeruję przekierowanie stderr na stdout i podłączenie do koloratora opartego na wzorach , takiego jak colortail lub multitail , lub specjalnych barwników , takich jak colorgcc lub colormake .
¹ pseudo-terminale. Rurki nie działałyby z powodu buforowania: źródło mogłoby zapisać do bufora, co przerwałoby synchroniczność z koloryzatorem.
źródło
LD_PRELOAD
sztuczki do przechwytywaniawrite
połączeń wydaje się być najbardziej odpowiednie, IMO (ale z drugiej strony mogą występować różnice w niektórych smakach * nix.)write
pojedynkę nie działałoby, ponieważ większość aplikacji nie wywołuje bezpośrednio, ale inna funkcja z niektórych bibliotek współdzielonych (jakprintf
), które wywoływałyby oryginałwrite
write
opakowanie syscall. Czy jest wbudowany w inne funkcje w Glibc?write
za pośrednictwem,LD_PRELOAD
jak opisano.Sprawdź
stderred
. WykorzystujeLD_PRELOAD
do hakalibc
„swrite()
połączeń, kolorowanie wszystkiestderr
wyjścia przechodząc do terminalu. (Domyślnie na czerwono.)źródło
Kolorowanie danych wejściowych użytkownika jest trudne, ponieważ w połowie przypadków jest ono wysyłane przez sterownik terminalu (z lokalnym echem), więc w takim przypadku żadna aplikacja działająca w tym terminalu może nie wiedzieć, kiedy użytkownik zamierza wpisać tekst i odpowiednio zmienić kolor wyjściowy . Tylko pseudo-terminalowy sterownik (w jądrze) wie (emulator terminala (jak xterm) wysyła mu pewne znaki po pewnym naciśnięciu klawisza, a sterownik terminala może odsyłać niektóre znaki dla echa, ale xterm nie może wiedzieć, czy są one z lokalne echo lub dane wyjściowe aplikacji na stronie slave pseudo terminala).
A potem jest inny tryb, w którym sterownikowi terminalu mówi się, żeby nie echo, ale aplikacja tym razem coś wypisuje. Aplikacja (podobnie jak te używające readline, takie jak gdb, bash ...) może wysłać to na swoim standardzie lub stderr, co będzie trudne do odróżnienia od czegoś, co wyprowadza dla innych rzeczy niż echo danych wejściowych użytkownika.
Następnie, aby odróżnić stdout aplikacji od stderr, istnieje kilka podejść.
Wiele z nich polega na przekierowaniu poleceń stdout i stderr do potoków i potoków odczytanych przez aplikację w celu pokolorowania. Są z tym dwa problemy:
Innym podejściem jest zmodyfikowanie aplikacji tak, aby kolorowała swoje standardowe i standardowe. Często nie jest to możliwe ani realistyczne.
Następnie sztuczką (w przypadku dynamicznie połączonych aplikacji) może być przejęcie (użycie
$LD_PRELOAD
jak w odpowiedzi Illilla ) funkcji wyjściowych wywoływanych przez aplikację w celu wypisania czegoś i umieszczenia w nich kodu określającego kolor pierwszego planu na podstawie tego, czy mają one coś wypisać na stderr lub stdout. Oznacza to jednak przejęcie każdej możliwej funkcji z biblioteki C i dowolnej innej biblioteki wykonującejwrite(2)
syscall bezpośrednio wywołanej przez aplikację, która może potencjalnie skończyć pisaniem czegoś na stdout lub stderr (printf, puts, perror ...), a nawet wtedy , co może zmienić jego zachowanie.Innym podejściem może być użycie sztuczek PTRACE jako
strace
lubgdb
zrobić, aby zaczepić się za każdym razem, gdywrite(2)
wywoływane jest wywołanie systemowe, i ustawić kolor wyjściowy na podstawie tego, czywrite(2)
jest on w deskryptorze pliku 1 czy 2.Jest to jednak dość duża rzecz.
Sztuką, z którą właśnie bawiłem
strace
się, jest przechwycenie samego siebie (co powoduje brudną robotę zaczepienia się przed każdym wywołaniem systemowym) za pomocą LD_PRELOAD, aby kazać mu zmienić kolor wyjściowy w zależności od tego, czy wykryłwrite(2)
na fd 1 czy 2)Patrząc na
strace
kod źródłowy, możemy zobaczyć, że wszystkie dane wyjściowe są wykonywane przezvfprintf
funkcję. Wszystko, co musimy zrobić, to przejąć tę funkcję.Opakowanie LD_PRELOAD wyglądałoby następująco:
Następnie kompilujemy to z:
I użyj go jako:
Zauważysz, jak w przypadku wymiany
some-cmd
zbash
, wierszu bash i co piszesz pojawia się na czerwono (stderr), natomiast zzsh
wydaje się na czarno (bo zsh dups stderr na nowy fd, aby wyświetlić jego szybka i echo).Wygląda na to, że działa zaskakująco dobrze nawet w aplikacjach, których nie spodziewałbyś się (takich jak te, które używają kolorów).
Tryb kolorowania jest wyprowadzany na
strace
stderr, który jest uważany za terminal. Jeśli aplikacja przekieruje swoje standardowe wyjście lub standardowe polecenie, nasz przejęty ciąg będzie nadal zapisywał sekwencje specjalne koloru na terminalu.To rozwiązanie ma swoje ograniczenia:
strace
: problemami z wydajnością, nie można uruchamiać innych poleceń PTRACE, takich jakstrace
lubgdb
w nim, ani problemów z setuid / setgidwrite
s na stdout / stderr każdego indywidualnego procesu. Tak na przykład, wsh -c 'echo error >&2'
,error
byłby zielony, ponieważecho
wyjścia na IT jej stdout (które sh przekierowany do stderr SH, ale wszystko strace widzi towrite(1, "error\n", 6)
). I insh -c 'seq 1000000 | wc'
,seq
robi wiele lub więcejwrite
do swojego standardu , więc opakowanie ostatecznie wyśle wiele (niewidocznych) sekwencji ucieczki do terminala.źródło
strace $CMD | vim -c ':set syntax=strace' -
.Oto dowód koncepcji, który zrobiłem jakiś czas temu.
Działa tylko w Zsh.
Zakłada również, że masz funkcję o nazwie setcolor.
Uproszczona wersja:
źródło
exec 2> >(rederr)
. Obie wersje będą miały problemy, o których wspomniałem w mojej odpowiedzi, dotyczące zmiany kolejności linii i ryzyka zniekształconego wyjścia (szczególnie w przypadku długich linii).seterr
musiałby być samodzielnym skryptem, a nie funkcją.Zobacz Hilite Mike'a Schiraldiego, który robi to dla jednego polecenia na raz. Mój własny wytrysk robi to przez całą sesję, ale ma też wiele innych funkcji / osobliwości, których możesz nie chcieć.
źródło
Niektóre wcześniejsze dyskusje na temat błędu serwera.
Zobacz także grc i pomocny blog na ten temat.
źródło