Вопрос: bash: print stderr в красном цвете


Есть ли способ сделать отображение bash STDERR сообщения красного цвета?


92
2017-08-26 21:10


Источник


Я думаю, bash никогда не будет раскрашивать свой результат: какая-то программа может что-то разобрать, а раскраска портит данные с экранированными последовательностями. Думаю, приложение GUI должно обрабатывать цвета. - kolypto


Ответы:


command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done)

81
2017-08-26 21:39



Большой! Но мне интересно, есть ли способ сделать это постоянным :) - kolypto
Отличный совет! Предложение: добавив >&2 прямо перед ; done), вывод, предназначенный для stderr, фактически записывается в stderr. Это полезно, если вы хотите зафиксировать нормальный выход программы. - henko
Следующие виды использования tput, и, на мой взгляд, несколько читабельнее: command 2> >(while read line; do echo -e "$(tput setaf 1)$line$(tput sgr0)" >&2; done) - Stefan Lasiewski
Я думаю, что выполнение двух процессов tput для каждой выходной строки не является элегантным вообще. Возможно, если вы сохраните вывод команд tput в переменной и используйте их для каждого эха. Но опять же, читаемость на самом деле не лучше. - Balázs Pozsár
Это решение не сохраняет пробелы, но мне нравится его краткость. IFS= read -r line должен помочь, но этого не делать. Не знаю, почему. - Max Murphy


Способ 1. Использование замены процесса:

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

Способ 2. Создайте функцию в сценарии bash:

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

Используйте его так:

$ color command

Оба метода покажут команду stderr в красном.

Продолжайте читать для объяснения того, как работает метод 2. Есть некоторые интересные функции, продемонстрированные этой командой.

  • color()... - Создает функцию bash, называемую цветом.
  • set -o pipefail - Это опция оболочки, которая сохраняет код возврата ошибки команды, выход которой передается в другую команду. Это делается в подоболочке, которая создается скобками, чтобы не изменять параметр pipefail во внешней оболочке.
  • "$@" - Выполняет аргументы функции как новую команду. "$@" эквивалентно "$1" "$2" ...
  • 2>&1 - перенаправляет stderr команды для stdout так что это становится sed«s stdin,
  • >&3 - Сокращение для 1>&3, это перенаправление stdout к новому временному файловому дескриптору 3, 3 попадает в stdout позже.
  • sed ... - Из-за переадресаций выше, sed«s stdin это stderr выполненной команды. Его функция состоит в том, чтобы окружать каждую строку цветовыми кодами.
  • $'...' Конструкция bash, которая заставляет ее понимать символы с обратным слэшем
  • .* - Соответствует всей строке.
  • \e[31m - escape-последовательность ANSI, которая вызывает следующие символы:
  • & - sed замените символ, который расширяется до всей согласованной строки (вся строка в этом случае).
  • \e[m - escape-последовательность ANSI, которая сбрасывает цвет.
  • >&2 - Сокращение для 1>&2, это перенаправление sed«s stdout в stderr,
  • 3>&1 - перенаправляет временный файловый дескриптор 3 Вернуться в stdout,

68
2018-04-23 20:53



+1 лучший ответ! Абсолютно недооцененный! - muhqu
Отличный ответ и даже лучшее объяснение - Daniel Serodio
Зачем вам нужно все дополнительное перенаправление? кажется излишним - qodeninja
@qodeninja Объяснение дает цель для перенаправления. Если вы можете найти более простой способ сделать это, я бы с удовольствием это увидел! - killdash9
Есть ли способ заставить его работать в zsh? - Eyal Levin


Вы также можете проверить stderred: https://github.com/sickill/stderred


22
2017-12-13 21:40



Вау, эта утилита велика, единственное, что ей понадобится, это иметь apt-репозиторий, который устанавливает его для всех пользователей, с одной строкой, не имея необходимости делать больше работы, чтобы включить его. - sorin
Казалось, что он хорошо работает, когда я тестировал его со сценарием сборки в отдельном терминале, но я не решаюсь использовать его глобально (в .bashrc). Спасибо хоть! - Joel Purra
В OS X El Capitan способ работы (DYLD_INSERT_LIBRARIES) «сломан» в системных двоичных файлах, поскольку они защищены SIP. Поэтому лучше использовать опции bash, указанные в других ответах. - hmijail
@hmijail для MacOS, пожалуйста, следуйте github.com/sickill/stderred/issues/60 поэтому мы можем найти обходное решение, частичное уже существует, но немного ошибочно. - sorin


http://sourceforge.net/projects/hilite/


13
2017-08-26 21:18





Способ создания STDERR Постоянно красный использует «exec» для перенаправления потоков. Добавьте в свой 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;'

Я уже писал об этом ранее: Как установить цвет шрифта для STDOUT и STDERR


10
2018-01-29 08:49



Связанный: unix.stackexchange.com/questions/367636/... - Blauhirn
Это лучший ответ на сегодняшний день; легко реализуется без установки / требует привилегий sudo и может быть обобщен ко всем командам. - Luke Davis
К сожалению, это не очень хорошо сочетается с цепочкой команд (команда && nextCommand || errorHandlerCommand). Выход ошибки выводится после вывода ошибкиHandlerCommand. - carlin.scott


Я создал сценарий оболочки, который реализует ответ Балаза Позара в чистом баше. Сохраните его в своих командах $ PATH и prefix, чтобы раскрасить их вывод.


    #! / Bin / Баш

    если [$ 1 == "--help"]; тогда
        echo «Выполняет команду и раскрашивает все ошибки»
        echo "Пример:` basename $ {0} `wget ..."
        echo "(c) o_O Tync, ICQ # 1227-700, Enjoy!"
        выход 0
        фи

    # Temp-файл, чтобы поймать все ошибки
    TMP_ERRS = $ (Mktemp)

    # Выполнение команды
    "$ @" 2>> (при чтении строки, do echo -e "\ e [01; 31m $ line \ e [0m" | tee --append $ TMP_ERRS; сделано)
    EXIT_CODE = $?

    # Показать все ошибки снова.
    если [-s "$ TMP_ERRS"]; тогда
        echo -e "\ n \ n \ n \ e [01; 31m === ОШИБКИ === \ e [0m"
        cat $ TMP_ERRS
        фи
    rm -f $ TMP_ERRS

    # Конец
    exit $ EXIT_CODE


6
2017-08-26 22:13



Это можно было бы сделать более эффективным, если бы «| tee ...» был поставлен после «сделано». - Juliano


Вы можете использовать такую ​​функцию


 #!/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


2
2017-08-26 22:29



Не решает проблему. Вы не предоставили способ отделить stderr от stdout, чего интересует O.P. - Jeremy Visser


У меня есть слегка измененная версия скрипта O_o Tync. Мне нужно было сделать эти моды для OS X Lion, и это не идеально, потому что сценарий иногда завершается до того, как завершена команда. Я добавил сон, но я уверен, что есть лучший способ.

#!/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

1
2018-06-08 17:37





Это решение работало для меня: https://superuser.com/questions/28869/immediately-tell-which-output-was-sent-to-stderr

Я поставил эту функцию в свою .bashrc или .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
}

Затем, например:

$ rse cat non_existing_file.txt

даст мне красный выход.


1
2017-08-25 09:16





версию, использующую 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
2018-06-04 10:04