Необходимо использовать kill
команда для этого.
Чтобы быть более подробными - необходимо указать правильный сигнал, т.е.
$ kill -TSTP $PID_OF_PROCESS
для приостановки процесса и
$ kill -CONT $PID_OF_PROCESS
для возобновления его. Зарегистрированный здесь.
Это - более трудная версия Шоу только stderr на экране, но записи и stdout и stderr в файл.
Приложения, работающие в терминале, используют один канал для общения с ним; приложения имеют два выходных порта, stdout и stderr, но они оба подключены к тому же каналу.
Можно соединить одного из них к другому каналу, добавить цвет к тому каналу и объединить эти два канала, но это вызовет две проблемы:
␛[31m
значит “переключатель для красного переднего плана”. Это означает, что, если некоторый вывод, предназначенный к stdout, прибывает так же, как некоторый вывод для stderr отображается, вывод будет искажен. (Еще хуже, если существует переключение канала посреди escape-последовательности, Вы будете видеть мусор.)В принципе было бы возможно записать программу, которая слушает на двух имуществах ¹, синхронно (т.е. не примет вход на одном канале, в то время как это обрабатывает вывод на другом канале), и сразу выводы к терминалу с соответствующими инструкциями по изменению цвета. Вы потеряли бы способность запустить программы, которые взаимодействуют с терминалом. Я не знаю ни о какой реализации этого метода.
Другой возможный подход должен был бы заставить программу производить надлежащие последовательности изменения цвета путем сцепления вокруг всех функций libc, которые звонят write
системный вызов в библиотеке, загруженной LD_PRELOAD
. См. ответ sickill для существующей реализации или ответ Stéphane Chazelas для смешанного подхода, который усиливает strace
.
На практике, если это применимо, я предлагаю перенаправить stderr к stdout и передать по каналу в основанный на шаблоне colorizer, такой как colortail или мультихвост или colorizers специального назначения, такой как colorgcc или colormake.
¹ псевдотерминалы. Каналы не работали бы из-за буферизации: источник мог записать в буфер, который повредит синхронность с colorizer.
Вот подтверждение концепции, которое я действительно некоторое время поддерживал.
Это только работает в zsh.
# make standard error red
rederr()
{
while read -r line
do
setcolor $errorcolor
echo "$line"
setcolor normal
done
}
errorcolor=red
errfifo=${TMPDIR:-/tmp}/errfifo.$$
mkfifo $errfifo
# to silence the line telling us what job number the background job is
exec 2>/dev/null
rederr <$errfifo&
errpid=$!
disown %+
exec 2>$errfifo
Это также предполагает, что у Вас есть функция, вызванная setcolor.
Упрощенная версия:
setcolor()
{
case "$1" in
red)
tput setaf 1
;;
normal)
tput sgr0
;;
esac
}
exec 2> >(rederr)
. Обе версии будут иметь проблемы, которые я упоминаю в своем ответе переупорядочения строк и риска искаженным выводом (особенно с длинными линиями).
– Gilles 'SO- stop being evil'
02.05.2011, 03:38
seterr
должен был бы быть автономный сценарий, не функция.
– Gilles 'SO- stop being evil'
02.05.2011, 10:09
Выезд stderred
. Это использует LD_PRELOAD
сцепляться с libc
write()
вызовы, колоризация все stderr
вывод, идущий в терминал. (В красном по умолчанию.)
Окрашивание ввода данных пользователем является трудным, потому что в половине случаев, это производится терминальным драйвером (с локальным эхом) так в этом случае, никакое приложение, работающее в том терминале, не может знать, когда пользователь собирается ввести текст и изменить цвет вывода соответственно. Только драйвер псевдотерминала (в ядре) знает (эмулятор терминала (как xterm) отправляет его, некоторые символы после некоторого нажатия клавиши и терминального драйвера могут передать некоторые символы обратно для эха, но xterm не может знать, является ли это от локального эха или от того, что приложение производило ведомой стороне псевдотерминала).
И затем, существует другой режим, где терминальному драйверу говорят не отозваться эхом, но приложение на этот раз производит что-то. Приложение (как те, которые используют readline как gdb, удар...), может отправить это на своем stdout или stderr, который будет трудным дифференцироваться от чего-то, что это производит для других вещей, чем реагирование на ввод данных пользователем.
Затем для дифференциации stdout приложения от его stderr существует несколько подходов.
Многие из них включают перенаправление команд stdout и stderr к каналам и тем каналам, считанным приложением для окраски его. Существует две проблемы с этим:
Другой подход должен изменить приложение так, чтобы это действительно окрасило свой stdout и stdin. Это часто не возможно или реалистично сделать.
Затем прием (для динамично связанных приложений) может быть должен угнать (использование $LD_PRELOAD
как в ответе sickill) функции вывода, вызванные приложением, чтобы произвести что-то и включать код в них, который выбирает основной цвет на основе того, ли предназначены они для вывода чего-то на stderr или stdout. Однако это означает угонять каждую возможную функцию из библиотеки C и любой другой библиотеки, которая делает a write(2)
syscall, непосредственно названный приложением, которое может потенциально закончить тем, что писало что-то на stdout или stderr (printf, помещает, perror...), и даже затем, который может изменить его поведение.
Другой подход мог быть должен использовать приемы PTRACE как strace
или gdb
сделайте для сцепления каждый раз write(2)
системный вызов называют и установил цвет вывода на основе ли write(2)
находится на дескрипторе файла 1 или 2.
Однако это - вполне большая вещь сделать.
Прием, с которым я просто играл, должен угнать strace
самостоятельно (который делает грязную работу сцепления себя перед каждым системным вызовом) использующий LD_PRELOAD, чтобы сказать этому изменять цвет вывода на основе того, обнаружило ли это a write(2)
на fd 1 или 2.
От взгляда на strace
исходный код, мы видим, что все, что он производит, сделано через vfprintf
функция. Все, что мы должны сделать, должно угнать ту функцию.
Обертка LD_PRELOAD была бы похожа:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
int vfprintf(FILE *outf, const char *fmt, va_list ap)
{
static int (*orig_vfprintf) (FILE*, const char *, va_list) = 0;
static int c = 0;
va_list ap_orig;
va_copy(ap_orig, ap);
if (!orig_vfprintf) {
orig_vfprintf = (int (*) (FILE*, const char *, va_list))
dlsym (RTLD_NEXT, "vfprintf");
}
if (strcmp(fmt, "%ld, ") == 0) {
int fd = va_arg(ap, long);
switch (fd) {
case 2:
write(2, "\e[31m", 5);
c = 1;
break;
case 1:
write(2, "\e[32m", 5);
c = 1;
break;
}
} else if (strcmp(fmt, ") ") == 0) {
if (c) write(2, "\e[m", 3);
c = 0;
}
return orig_vfprintf(outf, fmt, ap_orig);
}
Затем мы компилируем его с:
cc -Wall -fpic -shared -o wrap.so wrap.c -ldl
И используйте его как:
LD_PRELOAD=/path/to/wrap.so strace -qfo /dev/null -e write -s 0 env -u LD_PRELOAD some-cmd
Вы заметите как, если Вы замените some-cmd
с bash
, подсказка удара и что Вы вводите, появляется в красном (stderr) в то время как с zsh
это появляется в черном цвете (потому что zsh копирует stderr на новый fd для отображения его подсказки и эха).
Это, действительно кажется, работает удивительно хорошо даже на приложения, которые Вы ожидали бы не (как те, которые действительно используют цвета).
Окрашивающий режим производится на strace
stderr, который, как предполагается, является терминалом. Если приложение перенаправит свой stdout или stderr, то наш угнанный strace будет продолжать писать окрашивающие escape-последовательности на терминале.
То решение имеет свои ограничения:
strace
: проблемы производительности, Вы не можете выполнить другие команды PTRACE как strace
или gdb
в нем, или проблемы setuid/setgidwrite
s на stdout/stderr каждого отдельного процесса. Так, например, в sh -c 'echo error >&2'
, error
было бы зеленым потому что echo
производит его на его stdout (какой sh, перенаправленный к stderr sh, но весь strace видит, является a write(1, "error\n", 6)
). И в sh -c 'seq 1000000 | wc'
, seq
делает много или write
s к ее stdout, таким образом, обертка закончится вывод много (невидимых) escape-последовательностей к терминалу.strace $CMD | vim -c ':set syntax=strace' -
.
– Pablo A
27.08.2017, 17:46
LD_PRELOAD
обманите для прерыванияwrite
вызовы, кажется, являются самыми соответствующими, IMO (но с другой стороны, могли бы быть различия на определенном *, отклоняют разновидности.) – alex 02.05.2011, 16:24write
один не работал бы, поскольку большинство приложений не звонит непосредственно, но другая функция из некоторой общей библиотеки (какprintf
) это назвало бы оригиналwrite
– Stéphane Chazelas 02.11.2012, 01:02write
обертка syscall. Это встраивается в других функциях в Glibc? – Gilles 'SO- stop being evil' 02.11.2012, 01:13write
черезLD_PRELOAD
как Вы описываете. – Drew Noakes 10.11.2013, 16:41