Как установить цвет шрифта для STDOUT и STDERR
Я хочу различать сообщения STDOUT и STDERR в моем терминале.
Если script или команда печатает сообщение в терминале, я хочу различать цвета; возможно ли это?
(например, цвет шрифта stderr красный, а цвет шрифта stdout - синий.)
Пример (полужирный):
$date
Wed Jul 27 12:36:50 IST 2011
$datee
bash: datee: command not found
$alias ls
alias ls='ls --color=auto -F'
$aliass ls
bash: aliass: command not found
Ответы
Ответ 1
Вот хак, о котором я думал, и он работает:
Учитывая следующие псевдонимы для читаемости:
alias blue='echo -en "\033[36m"'
alias red='echo -en "\033[31m"'
alias formatOutput='while read line; do blue; echo $line; red; done'
Теперь вам нужно сначала установить цвет шрифта в вашем терминале на красный (как по умолчанию, который будет использоваться для stderr).
Затем запустите свою команду и пропустите stdout через formatOutput
, определенный выше (который просто печатает каждую строку как синюю, а затем сбрасывает цвет шрифта до красного):
shell$ red
shell$ ls / somenonexistingfile | formatOutput
Вышеуказанная команда будет печататься как в stderr, так и в stdout, и вы увидите, что линии окрашены по-разному.
Надеюсь, что это поможет
UPDATE:
Чтобы сделать это многоразовым, я поместил все это в маленький script:
$ cat bin/run
#!/bin/bash
echo -en "\033[31m" ## red
eval $* | while read line; do
echo -en "\033[36m" ## blue
echo $line
echo -en "\033[31m" ## red
done
echo -en "\033[0m" ## reset color
Теперь вы можете использовать это с любой командой:
$ run yourCommand
Ответ 2
Создайте функцию в оболочке bash или script:
color()(set -o pipefail;"[email protected]" 2>&1>&3|sed $'s,.*,\e[31m&\e[m,'>&2)3>&1
Используйте его следующим образом:
$ color command -program -args
Показывает команду stderr
красным цветом.
Продолжайте читать для объяснения того, как это работает. Есть некоторые интересные функции, продемонстрированные этой командой.
-
color()...
— Создает функцию bash, называемую цветом.
-
set -o pipefail
— Это опция оболочки, которая сохраняет код возврата ошибки команды, выход которой передается в другую команду. Это делается в подоболочке, которая создается скобками, чтобы не изменять параметр pipefail во внешней оболочке.
-
"[email protected]"
— Выполняет аргументы функции как новую команду. "[email protected]"
эквивалентно "$1" "$2" ...
-
2>&1
— Перенаправляет команду stderr
в команду stdout
, чтобы она стала sed
stdin
.
-
>&3
— Сокращение для 1>&3
, это перенаправляет stdout
в новый временный дескриптор файла 3
. 3
позже перенаправляется в stdout
.
-
sed ...
— Из-за переадресаций выше sed
stdin
является stderr
выполненной команды. Его функция состоит в том, чтобы окружать каждую строку цветовыми кодами.
-
$'...'
Конструкция bash, которая заставляет его понимать символы с обратным слэшем.
-
.*
— Совпадает со всей строкой.
-
\e[31m
— Последовательность escape-кода ANSI, которая вызывает следующие символы:
-
&
— Символ замены sed
, который расширяется до всей согласованной строки (вся строка в этом случае).
-
\e[m
— ANSI escape-последовательность, которая сбрасывает цвет.
-
>&2
— Сокращение для 1>&2
, это перенаправляет sed
stdout
на stderr
.
-
3>&1
— Перенаправляет временный дескриптор файла 3
обратно в stdout
.
Ответ 3
Я цвет stderr красный, связав дескриптор файла с пользовательской функцией, которая добавляет цвет ко всему, что проходит через него. Добавьте к следующему вашему .bashrc
:
export COLOR_RED="$(tput setaf 1)"
export COLOR_RESET="$(tput sgr0)"
exec 9>&2
exec 8> >(
perl -e '$|=1; while(sysread STDIN,$a,9999) {print
"$ENV{COLOR_RED}$a$ENV{COLOR_RESET}"}'
)
function undirect(){ exec 2>&9; }
function redirect(){ exec 2>&8; }
trap "redirect;" DEBUG
PROMPT_COMMAND='undirect;'
Так что происходит? Ловушка отладки выполняется непосредственно перед и сразу после выполнения команды. stderr, таким образом, перенаправляется до выполнения команды для включения красного вывода. PROMPT_COMMAND оценивается до отображения приглашения, и при этом я восстанавливаю stderr в нормальное состояние. Это необходимо, потому что PS1 и PS2 (ваше приглашение) печатаются поверх stderr, и я не хочу красную подсказку. volila, красный вывод над stderr!
Ответ 4
Вы должны проверить stderred: https://github.com/sickill/stderred
Ответ 5
Да это не возможно изначально. Вам придется взломать управление tty (в ядре).
Я как-то закончил небольшую обертку C до того, как увидел другие ответы:-)
Может быть ошибкой, а значения жестко запрограммированы, не используйте это, кроме как для тестирования.
#include "unistd.h"
#include "stdio.h"
#include <sys/select.h>
int main(int argc, char **argv)
{
char buf[1024];
int pout[2], perr[2];
pipe(pout); pipe(perr);
if (fork()!=0)
{
close(1); close(2);
dup2(pout[1],1); dup2(perr[1],2);
close(pout[1]); close(perr[1]);
execvp(argv[1], argv+1);
fprintf(stderr,"exec failed\n");
return 0;
}
close(pout[1]); close(perr[1]);
while (1)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(pout[0], &fds);
FD_SET(perr[0], &fds);
int max = pout[0] > perr[0] ? pout[0] : perr[0];
int v = select(max+1, &fds, NULL, NULL, NULL);
if (FD_ISSET(pout[0], &fds))
{
int r;
r = read(pout[0], buf, 1024);
if (!r) {close(pout[0]); continue;}
write(1, "\033[33m", 5);
write(1, buf, r);
write(1, "\033[0m", 4);
}
if (FD_ISSET(perr[0], &fds))
{
int r;
r = read(perr[0], buf, 1024);
if (!r) {close(perr[0]); continue;}
write(2, "\033[31m", 5);
write(2, buf, r);
write(2, "\033[0m", 4);
}
if (v <= 0) break;
}
return 0;
}
Изменить:. По сравнению с решением оболочки, это будет сохранять порядок строк/символов чаще. (Невозможно быть таким точным, как прямое чтение tty.) Нажатие ^ C не покажет уродливое сообщение об ошибке, и оно корректно ведет себя в этом примере:
./c_color_script sh -c "while true; do (echo -n a; echo -n b 1>&2) done"
Ответ 6
Я удивлен, что никто не понял, как цветные потоки stdio. Это будет красным цветом stderr для всей (суб) оболочки:
exec 3>&2
exec 2> >(sed -u 's/^\(.*\)$/'$'\e''[31m\1'$'\e''[m/' >&3)
В этом случае &3
будет удерживать исходный поток stderr.
Вы не должны передавать какие-либо команды exec
, а только перенаправлять. Этот специальный случай заставляет exec
заменять потоки stdio текущей (суб) оболочки на те, которые он получает.
Есть несколько предостережений:
- Так как
sed
будет постоянно работать в параллельной подоболочке, любой прямой вывод сразу после записи в цветной stdio, вероятно, будет бить sed
в tty
.
- Этот метод использует дескриптор файла FIFO; Узлы FIFO работают только в строках. Если вы не будете писать поток строк в поток, ваш вывод будет буферизован до появления новой строки. Это не буферизация на части
sed
: как работают эти типы файлов.
Самое сложное из предостережений - первое, но состояние гонки можно более или менее избегать, применяя подобную обработку ко всем выходам, даже если вы используете цвет по умолчанию.
Вы можете выполнить аналогичную обработку для одиночных команд по трубопроводу с той же командой sed
с обычным оператором трубы (|
). Трубопроводные цепи выполняются синхронно, поэтому никаких условий гонки не произойдет, хотя последняя команда в цепочке трубопроводов по умолчанию получает свою собственную подоболочку.