¿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)
>&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.
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 linedeberí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 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.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 ~/.bashrcdos 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 .bashrco .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 (evalpara 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)