Quiero configurar mi terminal para que stderr
se imprima en un color diferente que stdout
; Quizás rojo. Esto facilitaría distinguir los dos.
¿Hay alguna manera de configurar esto .bashrc
? Si no, ¿es esto posible?
Nota : Esta pregunta se fusionó con otra que solicitó stderr
, stdout
y el eco de entrada del usuario se emitirá en 3 colores diferentes . Las respuestas pueden estar abordando cualquiera de las preguntas.
Respuestas:
Esta es una versión más difícil de Mostrar solo stderr en pantalla pero escribe tanto stdout como stderr en el archivo .
Las aplicaciones que se ejecutan en el terminal usan un solo canal para comunicarse con él; las aplicaciones tienen dos puertos de salida, stdout y stderr, pero ambos están conectados al mismo canal.
Puede conectar uno de ellos a un canal diferente, agregar color a ese canal y fusionar los dos canales, pero esto causará dos problemas:
␛[31m
significa "cambiar a primer plano rojo". Esto significa que si alguna salida destinada a stdout llega justo cuando se muestra alguna salida para stderr, la salida tendrá un color incorrecto. (Aún peor, si hay un interruptor de canal en medio de una secuencia de escape, verá basura).En principio, sería posible escribir un programa que escuche en dos ptys¹, sincrónicamente (es decir, no acepte la entrada en un canal mientras procesa la salida en el otro canal), e inmediatamente saldrá al terminal con las instrucciones apropiadas de cambio de color. Perdería la capacidad de ejecutar programas que interactúan con el terminal. No sé de ninguna implementación de este método.
Otro enfoque posible sería hacer que el programa emita las secuencias de cambio de color adecuadas, enganchando todas las funciones de libc que llaman a la llamada del
write
sistema en una biblioteca cargada conLD_PRELOAD
. Vea la respuesta de sickill para una implementación existente, o la respuesta de Stéphane Chazelas para un enfoque mixto que aprovechastrace
.En la práctica, si corresponde, sugiero redirigir stderr a stdout y canalizarlo a un colorizador basado en patrones como colortail o multitail , o colorantes especiales como colorgcc o colormake .
¹ pseudo terminales. Las tuberías no funcionarían debido al almacenamiento en búfer: la fuente podría escribir en el búfer, lo que rompería la sincronía con el colorizador.
fuente
LD_PRELOAD
truco para interceptarwrite
llamadas parece ser el más apropiado, en mi opinión (pero, de nuevo, puede haber diferencias en ciertos sabores * nix.)write
solo no funcionaría ya que la mayoría de las aplicaciones no llaman directamente, sino otra función de alguna biblioteca compartida (comoprintf
) que llamaría al originalwrite
write
envoltorio de syscall. ¿Está incluido en otras funciones en Glibc?write
través de loLD_PRELOAD
que usted describe.Echa un vistazo
stderred
. Se utilizaLD_PRELOAD
para conectarlibc
laswrite()
llamadas a, coloreando toda lastderr
salida que va a un terminal. (En rojo por defecto).fuente
Colorear la entrada del usuario es difícil porque en la mitad de los casos, es emitida por el controlador del terminal (con eco local), por lo que ninguna aplicación que se ejecute en ese terminal puede saber cuándo el usuario va a escribir texto y cambiar el color de salida en consecuencia . Solo el controlador de pseudo-terminal (en el núcleo) sabe (el emulador de terminal (como xterm) le envía algunos caracteres al presionar alguna tecla y el controlador de terminal puede enviar algunos caracteres para eco, pero xterm no puede saber si son del eco local o de lo que sale la aplicación al lado esclavo del pseudo terminal).
Y luego, está el otro modo en el que se le dice al controlador del terminal que no repita, pero esta vez la aplicación genera algo. La aplicación (como las que usan readline como gdb, bash ...) puede enviar eso en su stdout o stderr, lo que será difícil de diferenciar de algo que genera para otras cosas que no sean hacer eco de la entrada del usuario.
Luego, para diferenciar el stdout de una aplicación de su stderr, hay varios enfoques.
Muchos de ellos implican redirigir los comandos stdout y stderr a tuberías y esas tuberías leídas por una aplicación para colorearlo. Hay dos problemas con eso:
Otro enfoque es modificar la aplicación para que coloree su stdout y stdin. A menudo no es posible ni realista hacerlo.
Entonces, un truco (para aplicaciones vinculadas dinámicamente) puede ser secuestrar (usando
$LD_PRELOAD
como en la respuesta de sickill ) las funciones de salida llamadas por la aplicación para generar algo e incluir código en ellas que establece el color de primer plano en función de si están destinadas a generar algo en stderr o stdout. Sin embargo, eso significa secuestrar todas las funciones posibles de la biblioteca C y de cualquier otra biblioteca quewrite(2)
realice una llamada al sistema directamente llamada por la aplicación que podría terminar escribiendo algo en stdout o stderr (printf, Put, Perror ...), e incluso entonces , eso puede modificar su comportamiento.Otro enfoque podría ser utilizar trucos PTRACE
strace
ogdb
engancharnos cada vezwrite(2)
que se llama a la llamada del sistema y establecer el color de salida en función de siwrite(2)
está en el descriptor de archivo 1 o 2.Sin embargo, eso es bastante importante.
Un truco con el que acabo de jugar es secuestrarse a
strace
sí mismo (que hace el trabajo sucio de engancharse antes de cada llamada al sistema) usando LD_PRELOAD, para decirle que cambie el color de salida en función de si ha detectado unwrite(2)
fd 1 o 2)Al mirar el
strace
código fuente, podemos ver que todo lo que sale se realiza a través de lavfprintf
función. Todo lo que necesitamos hacer es secuestrar esa función.El contenedor LD_PRELOAD se vería así:
Luego, lo compilamos con:
Y úsalo como:
Notarás cómo si reemplazas
some-cmd
conbash
, el indicador bash y lo quezsh
escribes aparece en rojo (stderr) mientras que aparece en negro (porque zsh dups stderr en un nuevo fd para mostrar su indicador y eco).Parece funcionar sorprendentemente bien incluso para aplicaciones que no esperarías (como las que usan colores).
El modo de coloración se emite en
strace
stderr, que se supone que es el terminal. Si la aplicación redirige su stdout o stderr, nuestra secuencia secuestrada seguirá escribiendo las secuencias de escape para colorear en el terminal.Esa solución tiene sus limitaciones:
strace
: problemas de rendimiento, no puede ejecutar otros comandos PTRACE comostrace
ogdb
en él, o problemas setuid / setgidwrite
s en stdout / stderr de cada proceso individual. Entonces, por ejemplo, ensh -c 'echo error >&2'
,error
sería verde porque loecho
genera en su stdout (que sh redirige a sh's stderr, pero todo lo que ve strace es awrite(1, "error\n", 6)
). Y ensh -c 'seq 1000000 | wc'
,seq
hace mucho owrite
s a la salida estándar, por lo que el contenedor va a terminar outputing un montón de (invisible) secuencias de escape a la terminal.fuente
strace $CMD | vim -c ':set syntax=strace' -
.Aquí hay una prueba de concepto que hice hace un tiempo.
Solo funciona en zsh.
También supone que tiene una función llamada setcolor.
Una versión simplificada:
fuente
exec 2> >(rederr)
. Ambas versiones tendrán los problemas que menciono en mi respuesta, de reordenar líneas y arriesgar la salida destrozada (particularmente con líneas largas).seterr
tendría que ser un script independiente, no una función.Ver de Mike Schiraldi Hilite que hace esto por un comando a la vez. Mi propio gush hace esto durante toda una sesión, pero también tiene muchas otras características / idiosincrasias que quizás no desee.
fuente
Alguna discusión previa sobre serverfault.
Ver también grc y un blog útil al respecto.
fuente