¿Hay alguna forma de hacer que bash muestre mensajes stderr en color rojo?
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.
¿Hay alguna forma de hacer que bash muestre mensajes stderr en color rojo?
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:
command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done)
>&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:
command 2> >(sed $'s,.*,\e[31m&\e[m,'>&2)
Método 2: crear una función en un script bash:
color()(set -o pipefail;"$@" 2>&1>&3|sed $'s,.*,\e[31m&\e[m,'>&2)3>&1
Úselo así:
$ color command
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 el stderr
comando a stdout
para que se convierta en sed
's stdin
.>&3
- Abreviatura de 1>&3
, esto redirige stdout
a un nuevo descriptor de archivo temporal 3
. 3
se enruta de nuevo stdout
más tarde.sed ...
- Debido a los redireccionamientos anteriores, sed
's stdin
es el stderr
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&
- El sed
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 de 1>&2
este redirige sed
's stdout
a stderr
.3>&1
- Redirige el descriptor de archivo temporal 3
nuevamente stdout
.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
.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:
exec 9>&2
exec 8> >(
while IFS='' read -r line || [ -n "$line" ]; do
echo -e "\033[31m${line}\033[0m"
done
)
function undirect(){ exec 2>&9; }
function redirect(){ exec 2>&8; }
trap "redirect;" DEBUG
PROMPT_COMMAND='undirect;'
He publicado sobre esto anteriormente: Cómo configurar el color de fuente para STDOUT y STDERR
source ~/.bashrc
dos veces esto, mi terminal básicamente se bloquea.
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
Puedes usar una función como esta
#!/bin/sh
color() {
printf '\033[%sm%s\033[m\n' "$@"
# usage color "31;5" "string"
# 0 default
# 5 blink, 1 strong, 4 underlined
# fg: 31 red, 32 green, 33 yellow, 34 blue, 35 purple, 36 cyan, 37 white
# bg: 40 black, 41 red, 44 blue, 45 purple
}
string="Hello world!"
color '31;1' "$string" >&2
Añado> & 2 para imprimir en stderr
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/bash
if [ $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 0
fi
# 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 again
if [ -s "$TMP_ERRS" ] ; then
echo -e "\n\n\n$(tput setaf 1) === ERRORS === "
cat $TMP_ERRS
else
echo "No errors collected in $TMP_ERRS"
fi
rm -f $TMP_ERRS
# Finish
exit $EXIT_CODE
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
:
# 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>&1 1>&2 2>&3 | sed -e "s/^\(.*\)$/$(echo -en \\033)[31;1m\1$(echo -en \\033)[0m/") 3>&1 1>&2 2>&3
}
Entonces, por ejemplo:
$ rse cat non_existing_file.txt
me dará una salida roja.
set -o pipefail;
antes (eval
para el código de salida de redireccionamiento
"
a eval para preservar espacios en los argumentos
usando xargs e printf:
command 2> >(xargs -0 printf "\e[31m%s\e[m" >&2)