Supongo que bash nunca coloreará su salida: algunos programas pueden querer analizar algo, y la coloración estropeará los datos con secuencias escapadas. Una aplicación GUI debería manejar colores, supongo.
kolypto
La combinación de la respuesta de Balázs Pozsár y killdash9 da la nitidez: function color { "$@" 2> >(sed $'s,.*,\e[31m&\e[m,') } funciona para bash y zsh. No se puede agregar esto como una respuesta b / c reputación.
Heinrich Hartmann
1
Estoy esperando una respuesta que modifique bash para hacer esto. Todas las soluciones a continuación en realidad modifican stderr y posiblemente incluso reordenan wrt stdout, lo que rompe las cosas cuando la secuencia de bytes exacta de stderr debe conservarse, por ejemplo, cuando se realiza la tubería.
¡Excelente! Pero me pregunto si hay una manera de hacerlo permanente :)
kolypto
99
Gran consejo! Sugerencia: al agregar >&2justo antes ; done), el resultado destinado a stderr en realidad se escribe en stderr. Eso es útil si desea capturar la salida normal del programa.
henko
8
Los siguientes usos tput, y es un poco más legible en mi opinión:command 2> >(while read line; do echo -e "$(tput setaf 1)$line$(tput sgr0)" >&2; done)
Stefan Lasiewski
2
Creo que ejecutar 2 procesos tput para cada línea de salida no es elegante en absoluto. Quizás si almacena la salida de los comandos tput en una variable y los usa para cada eco. Pero, de nuevo, la legibilidad no es realmente mejor.
Balázs Pozsár
1
Esta solución no conserva los espacios en blanco, pero me gusta por su brevedad. IFS= read -r linedebería ayudar pero no lo hace. No estoy seguro de por qué.
Ambos métodos mostrarán los comandos stderren rojo.
Sigue leyendo para obtener una explicación de cómo funciona el método 2. Hay algunas características interesantes demostradas por este comando.
color()... - Crea una función bash llamada color.
set -o pipefail- Esta es una opción de shell que conserva el código de retorno de error de un comando cuya salida se canaliza a otro comando. Esto se hace en un subshell, que se crea entre paréntesis, para no cambiar la opción pipefail en el shell externo.
"$@"- Ejecuta los argumentos de la función como un nuevo comando. "$@"es equivalente a"$1" "$2" ...
2>&1- Redirige el stderrcomando a stdoutpara que se convierta en sed's stdin.
>&3- Abreviatura de 1>&3, esto redirige stdouta un nuevo descriptor de archivo temporal 3. 3se enruta de nuevo stdoutmás tarde.
sed ...- Debido a los redireccionamientos anteriores, sed's stdines el stderrdel comando ejecutado. Su función es rodear cada línea con códigos de color.
$'...' Una construcción bash que hace que comprenda los caracteres con barra invertida
.* - Coincide con toda la línea.
\e[31m - La secuencia de escape ANSI que hace que los siguientes caracteres sean rojos
&- El sedcarácter de reemplazo que se expande a toda la cadena coincidente (la línea completa en este caso).
\e[m - La secuencia de escape ANSI que restablece el color.
>&2- Abreviatura de 1>&2este redirige sed's stdouta stderr.
3>&1- Redirige el descriptor de archivo temporal 3nuevamente stdout.
¿Por qué necesita hacer toda la redirección adicional? parece exagerado
qodeninja 02 de
1
¿Hay alguna manera de hacerlo funcionar zsh?
Eyal Levin
1
ZSH no reconoce los formularios de redireccionamiento abreviado. Solo necesita dos 1 más, es decir:zsh: color()(set -o pipefail;"$@" 2>&1 1>&3|sed $'s,.*,\e[31m&\e[m,'1>&2)3>&1
Wow, esta utilidad es genial, lo único que necesitaría es tener un repositorio apto que lo instale para todos los usuarios, con una línea, sin tener que hacer más trabajo para habilitarlo.
sorin
Parecía funcionar bien cuando lo probé con un script de compilación en un terminal separado, pero dudo en usarlo globalmente (en .bashrc). Gracias sin embargo!
Joel Purra
2
En OS X El Capitan, la forma en que funciona (DYLD_INSERT_LIBRARIES) está "dañada" en los archivos binarios del sistema porque están protegidos por SIP. Por lo tanto, podría ser mejor usar las opciones de bash dadas en otras respuestas.
hmijail
1
@hmijail para MacOS, siga github.com/sickill/stderred/issues/60 para que podamos encontrar una solución, ya existe una parcial pero está un poco defectuosa.
sorin
15
La manera bash de hacer que stderr permanezca rojo permanentemente es usar 'exec' para redirigir las transmisiones. Agregue lo siguiente a su bashrc:
Esta es la mejor respuesta con diferencia; fácil de implementar sin instalación / que requiere privilegio sudo, y se puede generalizar a todos los comandos.
Luke Davis el
1
Lamentablemente, esto no funciona bien con el encadenamiento de comandos (comando && nextCommand || errorHandlerCommand). La salida de error va después de la salida de errorHandlerCommand.
carlin.scott
1
Del mismo modo, si hago source ~/.bashrcdos veces esto, mi terminal básicamente se bloquea.
Dolph
@Dolf: En mi bashrc, me protejo fácilmente de esto con una declaración if circundante para evitar que este código se vuelva a cargar. De lo contrario, el problema es la redirección 'exec 9> & 2' después de que la redirección ya haya tenido lugar. Tal vez cámbielo a una constante si sabe dónde apunta originalmente> 2.
Hice un script de envoltura que implementa la respuesta de Balázs Pozsár en bash puro. Guárdelo en sus comandos $ PATH y prefijo para colorear su salida.
#! / bin / bash
if [$ 1 == "--help"]; entonces
echo "Ejecuta un comando y colorea todos los errores ocurridos"
echo "Ejemplo:` basename $ {0} `wget ..."
echo "(c) o_O Tync, ICQ # 1227-700, ¡Disfruta!"
salida 0
fi
# Archivo temporal para detectar todos los errores
TMP_ERRS = $ (mktemp)
# Ejecutar comando
"$ @" 2>> (mientras lee la línea; do echo -e "\ e [01; 31m $ line \ e [0m" | tee --append $ TMP_ERRS; hecho)
EXIT_CODE = $?
# Mostrar todos los errores nuevamente
si [-s "$ TMP_ERRS"]; entonces
echo -e "\ n \ n \ n \ e [01; 31m === ERRORES === \ e [0m"
cat $ TMP_ERRS
fi
rm -f $ TMP_ERRS
# Terminar
salir $ EXIT_CODE
No aborda el problema. No ha proporcionado una forma de separar stderr de stdout, que es lo que le interesa al OP.
Jeremy Visser
1
Tengo una versión ligeramente modificada del script de O_o Tync. Necesitaba hacer estas modificaciones para OS X Lion y no es perfecto porque el script a veces se completa antes que el comando envuelto. He añadido un sueño, pero estoy seguro de que hay una mejor manera.
#!/bin/bashif[ $1 =="--help"];then
echo "Executes a command and colorizes all errors occured"
echo "Example: `basename ${0}` wget ..."
echo "(c) o_O Tync, ICQ# 1227-700, Enjoy!"
exit 0fi# Temp file to catch all errors
TMP_ERRS=`mktemp /tmp/temperr.XXXXXX`|| exit 1# Execute command"$@"2>>(while read line;do echo -e "$(tput setaf 1)$line\n"| tee -a $TMP_ERRS;done)
EXIT_CODE=$?
sleep 1# Display all errors againif[-s "$TMP_ERRS"];then
echo -e "\n\n\n$(tput setaf 1) === ERRORS === "
cat $TMP_ERRSelse
echo "No errors collected in $TMP_ERRS"fi
rm -f $TMP_ERRS# Finish
exit $EXIT_CODE
# Red STDERR# rse <command string>function rse(){# We need to wrap each phrase of the command in quotes to preserve arguments that contain whitespace# Execute the command, swap STDOUT and STDERR, colour STDOUT, swap back((eval $(for phrase in"$@";do echo -n "'$phrase' ";done))3>&11>&22>&3| sed -e "s/^\(.*\)$/$(echo -en \\033)[31;1m\1$(echo -en \\033)[0m/")3>&11>&22>&3}
function color { "$@" 2> >(sed $'s,.*,\e[31m&\e[m,') }
funciona para bash y zsh. No se puede agregar esto como una respuesta b / c reputación.Respuestas:
fuente
>&2
justo antes; done)
, el resultado destinado a stderr en realidad se escribe en stderr. Eso es útil si desea capturar la salida normal del programa.tput
, y es un poco más legible en mi opinión:command 2> >(while read line; do echo -e "$(tput setaf 1)$line$(tput sgr0)" >&2; done)
IFS= read -r line
debería ayudar pero no lo hace. No estoy seguro de por qué.Método 1: usar la sustitución del proceso:
Método 2: crear una función en un script bash:
Úselo así:
Ambos métodos mostrarán los comandos
stderr
en rojo.Sigue leyendo para obtener una explicación de cómo funciona el método 2. Hay algunas características interesantes demostradas por este comando.
color()...
- Crea una función bash llamada color.set -o pipefail
- Esta es una opción de shell que conserva el código de retorno de error de un comando cuya salida se canaliza a otro comando. Esto se hace en un subshell, que se crea entre paréntesis, para no cambiar la opción pipefail en el shell externo."$@"
- Ejecuta los argumentos de la función como un nuevo comando."$@"
es equivalente a"$1" "$2" ...
2>&1
- Redirige elstderr
comando astdout
para que se convierta ensed
'sstdin
.>&3
- Abreviatura de1>&3
, esto redirigestdout
a un nuevo descriptor de archivo temporal3
.3
se enruta de nuevostdout
más tarde.sed ...
- Debido a los redireccionamientos anteriores,sed
'sstdin
es elstderr
del comando ejecutado. Su función es rodear cada línea con códigos de color.$'...'
Una construcción bash que hace que comprenda los caracteres con barra invertida.*
- Coincide con toda la línea.\e[31m
- La secuencia de escape ANSI que hace que los siguientes caracteres sean rojos&
- Elsed
carácter de reemplazo que se expande a toda la cadena coincidente (la línea completa en este caso).\e[m
- La secuencia de escape ANSI que restablece el color.>&2
- Abreviatura de1>&2
este redirigesed
'sstdout
astderr
.3>&1
- Redirige el descriptor de archivo temporal3
nuevamentestdout
.fuente
zsh
?zsh: color()(set -o pipefail;"$@" 2>&1 1>&3|sed $'s,.*,\e[31m&\e[m,'1>&2)3>&1
También puede consultar stderred: https://github.com/sickill/stderred
fuente
.bashrc
). Gracias sin embargo!La manera bash de hacer que stderr permanezca rojo permanentemente es usar 'exec' para redirigir las transmisiones. Agregue lo siguiente a su bashrc:
He publicado sobre esto anteriormente: Cómo configurar el color de fuente para STDOUT y STDERR
fuente
source ~/.bashrc
dos veces esto, mi terminal básicamente se bloquea.http://sourceforge.net/projects/hilite/
fuente
Hice un script de envoltura que implementa la respuesta de Balázs Pozsár en bash puro. Guárdelo en sus comandos $ PATH y prefijo para colorear su salida.
fuente
Puedes usar una función como esta
Añado> & 2 para imprimir en stderr
fuente
Tengo una versión ligeramente modificada del script de O_o Tync. Necesitaba hacer estas modificaciones para OS X Lion y no es perfecto porque el script a veces se completa antes que el comando envuelto. He añadido un sueño, pero estoy seguro de que hay una mejor manera.
fuente
Esta solución funcionó para mí: https://superuser.com/questions/28869/immediately-tell-which-output-was-sent-to-stderr
He puesto esta función en mi
.bashrc
o.zshrc
:Entonces, por ejemplo:
me dará una salida roja.
fuente
set -o pipefail;
antes(eval
para el código de salida de redireccionamiento"
a eval para preservar espacios en los argumentosusando xargs e printf:
fuente
una versión con fifos
fuente