sviluppo-web-qa.it

bash: stampa stderr di colore rosso

C'è un modo per visualizzare bash stderr messaggi di colore rosso?

124
kolypto
command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done)
103
Balázs Pozsár

Metodo 1: utilizzare la sostituzione del processo:

command 2> >(sed $'s,.*,\e[31m&\e[m,'>&2)

Metodo 2: creare una funzione in uno script bash:

color()(set -o pipefail;"[email protected]" 2>&1>&3|sed $'s,.*,\e[31m&\e[m,'>&2)3>&1

Usalo in questo modo:

$ color command

Entrambi i metodi mostreranno il comando stderr in rosso.

Continua a leggere per una spiegazione di come funziona il metodo 2. Ci sono alcune caratteristiche interessanti dimostrate da questo comando.

  • color()... - Crea una funzione bash chiamata color.
  • set -o pipefail - Questa è un'opzione Shell che conserva il codice di ritorno dell'errore di un comando il cui output viene reindirizzato in un altro comando. Questo viene fatto in una subshell, creata dalle parentesi, in modo da non modificare l'opzione pipefail nella Shell esterna.
  • "[email protected]" - Esegue gli argomenti per la funzione come nuovo comando. "[email protected]" Equivale a "$1" "$2" ...
  • 2>&1 - Reindirizza stderr del comando su stdout in modo che diventi sed di stdin.
  • >&3 - Abbreviazione di 1>&3, Reindirizza stdout a un nuovo descrittore di file temporaneo 3. 3 Viene reindirizzato in stdout in seguito.
  • sed ... - A causa dei reindirizzamenti sopra, sed di stdin è il stderr del comando eseguito. La sua funzione è di circondare ogni riga con codici colore.
  • $'...' Un costrutto bash che gli fa capire i caratteri con escape backslash
  • .* - Corrisponde all'intera riga.
  • \e[31m - La sequenza di escape ANSI che fa diventare rossi i seguenti caratteri
  • & - Il carattere di sostituzione sed che si espande all'intera stringa corrispondente (l'intera riga in questo caso).
  • \e[m - La sequenza di escape ANSI che reimposta il colore.
  • >&2 - Abbreviazione di 1>&2, Reindirizza sed di stdout a stderr.
  • 3>&1: Reindirizza il descrittore di file temporaneo 3 Su stdout.
93
killdash9

Puoi anche dare un'occhiata a stderred: https://github.com/sickill/stderred

29
sickill

Il modo bash di rendere stderr permanentemente rosso sta usando 'exec' per reindirizzare i flussi. Aggiungi quanto segue al tuo 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;'

Ho precedentemente pubblicato su questo: Come impostare il colore del carattere per STDOUT e STDERR

17
gospes
14
quaie

Ho realizzato una sceneggiatura avvolgente che implementa la risposta di Balázs Pozsár in puro bash. Salvalo nei comandi $ PATH e prefisso per colorarne l'output.

 
 #!/bin/bash 
 
 se [$ 1 == "--help"]; then 
 echo "Esegue un comando e colora tutti gli errori occorsi" 
 echo "Esempio:` basename $ {0} `wget ..." 
 echo "(c) o_O Tync , ICQ # 1227-700, Divertiti! "
 Exit 0 
 Fi 
 
 # File temporaneo per rilevare tutti gli errori 
 TMP_ERRS = $ (mktemp ) 
 
 # Esegui comando 
 "$ @" 2>> (mentre leggi la riga; fai l'eco -e "\ e [01; 31m $ line\e [0m" | tee --append $ TMP_ERRS; done) 
 EXIT_CODE = $? 
 
 # Visualizza di nuovo tutti gli errori 
 se [-s "$ TMP_ERRS"]; quindi 
 echo -e "\ n\n\n\e [01; 31m === ERRORI ===\e [0m" 
 cat $ TMP_ERRS 
 fi 
 rm -f $ TMP_ERRS 
 
 # Fine 
 uscita $ EXIT_CODE 
 
7
kolypto

Puoi usare una funzione come questa


 #!/bin/sh

color() {
      printf '\033[%sm%s\033[m\n' "[email protected]"
      # 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
</ Code>

Aggiungo> & 2 per stampare su stderr

3
Ali Mezgani

Questa soluzione ha funzionato per me: https://superuser.com/questions/28869/immediately-tell-which-output-was-sent-to-stderr

Ho inserito questa funzione nel mio .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 "[email protected]"; 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
}

Quindi ad esempio:

$ rse cat non_existing_file.txt

mi darà un risultato rosso.

1
Eyal Levin

usando xargs e printf:

command 2> >(xargs -0 printf "\e[31m%s\e[m" >&2)
1
Carlos Barcellos

Ho una versione leggermente modificata della sceneggiatura di O_o Tync. Avevo bisogno di creare queste mod per OS X Lion e non è perfetto perché lo script a volte si completa prima del comando wrapping. Ho aggiunto un sonno ma sono sicuro che c'è un modo migliore.

#!/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
   "[email protected]" 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
1
Cliff

una versione che utilizza fifos

mkfifo errs
stdbuf -o0 -e0 -i0 grep . foo | while read line; do echo -e "\e[01;31m$line  \e[0m" >&2; done &
stdbuf -o0 -e0 -i0 sh $script 2>errs
0
untore