Я хочу настроить свой терминал так, чтобы stderr
он печатался другим цветом, чем stdout
; возможно красный. Это облегчит различие между ними.
Есть ли способ настроить это в .bashrc
? Если нет, возможно ли это?
Примечание . Этот вопрос был объединен с другим вопросом, который запрашивался stderr
, stdout
и пользовательский ввод эха выводился в 3 разных цветах . Ответы могут касаться любого вопроса.
Ответы:
Это более сложная версия Показать только stderr на экране, но записать как stdout, так и stderr в файл .
Приложения, работающие в терминале, используют один канал для связи с ним; приложения имеют два выходных порта, stdout и stderr, но оба они подключены к одному каналу.
Вы можете подключить один из них к другому каналу, добавить цвет к этому каналу и объединить два канала, но это вызовет две проблемы:
␛[31m
означает «переключиться на красный передний план». Это означает, что если какой-то вывод, предназначенный для stdout, поступает так же, как выводится какой-то вывод для stderr, вывод будет окрашен в неверный цвет. (Еще хуже, если в середине escape-последовательности есть переключатель каналов, вы увидите мусор.)В принципе, было бы возможно написать программу, которая прослушивает два ptys¹, синхронно (то есть не будет принимать входные данные на одном канале, пока обрабатывает выходные данные на другом канале), и немедленно выводит на терминал соответствующие инструкции по изменению цвета. Вы потеряете способность запускать программы, которые взаимодействуют с терминалом. Я не знаю ни одной реализации этого метода.
Другой возможный подход заключается в том, чтобы заставить программу выводить правильные последовательности изменения цвета, подключая все функции libc, которые вызывают
write
системный вызов в библиотеке, загруженнойLD_PRELOAD
. См . Ответ Седилл для существующей реализации или ответ Стефана Шазеласа для смешанного подхода, который используетstrace
.На практике, если это применимо, я предлагаю перенаправлять поток ошибок на стандартный вывод и трубопроводов в основе шаблонов Colorizer такой , как colortail или multitail или colorizers специального назначения , такие как colorgcc или colormake .
¹ псевдо-терминалы. Каналы не будут работать из-за буферизации: источник может записывать в буфер, что нарушит синхронность с колоризатором.
источник
LD_PRELOAD
трюка для перехватаwrite
вызовов кажется наиболее подходящим, IMO (но, опять же, могут быть различия в некоторых разновидностях * nix.)write
одиночку не будет работать, так как большинство приложений не вызывают напрямую, но другая функция из некоторой общей библиотеки (напримерprintf
), которая будет вызывать оригиналwrite
write
перехватить оболочку системного вызова. Это встроено в другие функции в Glibc?write
через,LD_PRELOAD
как вы описываете.Проверьте
stderred
. Он используетLD_PRELOAD
для подключения кlibc
«swrite()
вызовов, раскрашивание всехstderr
выходных собирается терминал. (По умолчанию красным)источник
Раскрашивать пользовательский ввод сложно, потому что в половине случаев он выводится драйвером терминала (с локальным эхом), поэтому в этом случае ни одно приложение, работающее на этом терминале, не может знать, когда пользователь собирается набирать текст и соответственно изменять цвет вывода. , Только псевдо-терминальный драйвер (в ядре) знает (эмулятор терминала (например, xterm) отправляет ему несколько символов при некотором нажатии, а драйвер терминала может отправлять обратно некоторые символы для эха, но xterm не может знать, получены ли они из локальный эхо или из того, что приложение выводит на ведомую сторону псевдотерминала).
И затем, есть другой режим, в котором драйвер терминала получает указание не отображать эхо, но приложение на этот раз что-то выводит. Приложение (например, использующее readline, такое как gdb, bash ...) может отправлять это на свой стандартный вывод или стандартный поток ошибок, что будет трудно отличить от чего-то, что оно выводит для других вещей, чем вывод пользовательского ввода.
Затем, чтобы отличить стандартный вывод приложения от стандартного, существует несколько подходов.
Многие из них включают в себя перенаправление команд stdout и stderr на каналы, и эти каналы читаются приложением для его раскрашивания. Есть две проблемы с этим:
Другой подход состоит в том, чтобы изменить приложение так, чтобы оно окрашивало свои stdout и stdin. Это часто невозможно или реально сделать.
Тогда уловка (для динамически связанных приложений) может заключаться в том, чтобы захватить (используя,
$LD_PRELOAD
как в ответе sickill ) функции вывода, вызываемые приложением для вывода чего-либо, и включать в них код, который устанавливает цвет переднего плана на основе того, предназначены ли они для вывода чего-либо на стандартный вывод или стандартный вывод. Тем не менее, это означает угон каждой возможной функции из библиотеки C и любой другой библиотеки, которая выполняетwrite(2)
системный вызов, вызываемый напрямую приложением, который может в конечном итоге записать что-то на stdout или stderr (printf, put, perror ...) и даже тогда , что может изменить его поведение.Другой подход может состоять в том, чтобы использовать приемы PTRACE как
strace
илиgdb
сделать, чтобы перехватывать себя каждый раз, когдаwrite(2)
вызывается системный вызов, и устанавливать выходной цвет в зависимости от того, включен лиwrite(2)
дескриптор файла 1 или 2.Тем не менее, это довольно большая вещь, чтобы сделать.
Уловка, с которой я только что играл, состоит в том, чтобы
strace
перехватить саму себя (которая делает грязную работу перехвата перед каждым системным вызовом), используя LD_PRELOAD, чтобы сказать ему, чтобы он изменял выходной цвет в зависимости от того, обнаружил ли онwrite(2)
на fd 1 или 2.Посмотрев на
strace
исходный код, мы видим, что все его выходные данные выполняются с помощьюvfprintf
функции. Все, что нам нужно сделать, это взломать эту функцию.Оболочка LD_PRELOAD будет выглядеть так:
Затем мы компилируем это:
И использовать его как:
Вы заметите, как, если вы замените
some-cmd
наbash
, приглашение bash и то, что выzsh
набираете, отображаются красным (stderr), а с ним - черным (потому что zsh переводит stderr на новый fd, чтобы отобразить его приглашение и эхо).Кажется, он работает на удивление хорошо даже для приложений, которые вы не ожидаете (например, те, которые используют цвета).
Режим окраски выводится на
strace
's stderr, который считается терминалом. Если приложение перенаправляет свой stdout или stderr, наш угнанный страйс будет продолжать записывать escape-последовательности окраски на терминале.Это решение имеет свои ограничения:
strace
: проблемам с производительностью, вы не можете запускать другие команды PTRACE, такие какstrace
илиgdb
внутри него, или проблемы с setuid / setgidwrite
s на stdout / stderr каждого отдельного процесса. Так, например, insh -c 'echo error >&2'
,error
будет зеленым, потому чтоecho
выводит его на свой стандартный вывод (который sh перенаправляется на stderr sh, но все стрисы видят awrite(1, "error\n", 6)
). И, insh -c 'seq 1000000 | wc'
,seq
делает много илиwrite
s для своего стандартного вывода, так что обертка в конечном итоге будет выводить много (невидимых) escape-последовательностей в терминал.источник
strace $CMD | vim -c ':set syntax=strace' -
,Вот подтверждение концепции, которую я сделал некоторое время назад.
Это работает только в Zsh.
Также предполагается, что у вас есть функция с именем setcolor.
Упрощенная версия:
источник
exec 2> >(rederr)
. Обе версии будут иметь проблемы, о которых я упоминал в своем ответе, о переупорядочении строк и риске искаженного вывода (особенно с длинными линиями).seterr
должен быть автономный скрипт, а не функция.См Майк Schiraldi в HILITE , который делает это для одной команды в то время. Моя собственная радость делает это для всей сессии, но также имеет много других особенностей / особенностей, которые вы, возможно, не захотите.
источник
Некоторое предыдущее обсуждение о сбое сервера.
Смотрите также grc и полезный блог об этом.
источник