Показать stdout и stderr в двух отдельных потоках

12

Я ищу способ визуально разделить stdout и stderr, чтобы они не чередовались и чтобы их можно было легко идентифицировать. В идеале stdout и stderr должны иметь отдельные области на экране, в которых они отображаются, например, в разных столбцах. Например, вывод, который выглядел бы так:

~$ some command
some useful output info
ERROR: an error
more output
ERROR: has occurred
another message
~$ 

вместо этого будет выглядеть примерно так:

~$ some command          |
some useful output info  |
more output              |  ERROR: an error
another message          |  ERROR: has occurred
~$                       |
Зои Хьюлл
источник
Этот вопрос, кажется, не задает одно и то же, и ни один из ответов не дает того, что спрашивается здесь.
Майкл Гомер
2
Было бы полезно перенаправить потоки в два разных файла журнала, а затем использовать что-то вроде MultiTail на них? vanheusden.com/multitail
Кусалананда
Утилита аннотирования-вывода выглядит полезной, или вам нужен вывод в столбцах?
Джефф Шаллер

Ответы:

4

Вы можете использовать screenфункцию вертикального разделения GNU :

#! /bin/bash -
tmpdir=$(mktemp -d) || exit
trap 'rm -rf "$tmpdir"' EXIT INT TERM HUP

FIFO=$tmpdir/FIFO
mkfifo "$FIFO" || exit

conf=$tmpdir/conf

cat > "$conf" << 'EOF' || exit
split -v
focus
screen -t stderr sh -c 'tty > "$FIFO"; read done < "$FIFO"'
focus
screen -t stdout sh -c 'read tty < "$FIFO"; eval "$CMD" 2> "$tty"; echo "[Command exited with status $?, press enter to exit]"; read prompt; echo done > "$FIFO"'
EOF

CMD="$*"
export FIFO CMD

screen -mc "$conf"

Использовать, например, как:

that-script 'ls / /not-here'

Идея состоит в том, что он запускает экран с временным файлом конфигурации, который запускает два окна экрана в вертикальной раскладке. В первом случае мы запускаем вашу команду с подключенным stderr ко второму.

Мы используем именованный канал для второго окна, чтобы сообщить свое tty-устройство первому, а также для первого, чтобы сообщить второму, когда команда выполнена.

Другое преимущество по сравнению с конвейерным подходом состоит в том, что команды stdout и stderr по-прежнему подключены к tty-устройствам, поэтому это не влияет на буферизацию. Обе панели также можно прокручивать вверх и вниз независимо (в screenрежиме копирования).

Если вы запустите оболочку в bashинтерактивном режиме с этим сценарием, вы заметите, что подсказка будет отображаться во втором окне, а оболочка будет читать то, что вы вводите в первом окне, когда эти оболочки выводят свою подсказку на stderr.

В случае bash, эхо того, что вы вводите, также появится во втором окне, так как это эхо выводится оболочкой (readline в случае bash) также на stderr. С некоторыми другими оболочками, такими как ksh93, он будет отображаться в первом окне ( вывод эха драйвером оконечного устройства, а не оболочкой), если вы не включили оболочку emacsили viрежим с помощью set -o emacsили set -o vi.

Стефан Шазелас
источник
1

Это уродливое решение, основанное на annotate-outputсценарии Debian ANNOTATE-OUTPUT (1) . Не уверен, что это то, что вы ищете, но с чего можно начать:

#!/bin/bash 

readonly col=150 # column to start error output 

add_out ()
{
    while IFS= read -r line; do
        echo "$1: $line"
    done
    if [ ! -z "$line" ]; then
        echo -n "$1: $line"
    fi
}

add_err ()
{
    while IFS= read -r line; do
        printf "%*s  %s %s: %s\n" $col "|" "$1" "$line"
    done
    if [ ! -z "$line" ]; then
        printf "%*s %s: %s" $col "$1" "$line"
    fi
}

cleanup() { __st=$?; rm -rf "$tmp"; exit $__st; }
trap cleanup 0
trap 'exit $?' 1 2 13 15

tmp=$(mktemp -d --tmpdir annotate.XXXXXX) || exit 1
OUT=$tmp/out
ERR=$tmp/err

mkfifo $OUT $ERR || exit 1

add_out OUTPUT < $OUT &
add_err ERROR < $ERR &

echo "I: Started $@"
"$@" > $OUT 2> $ERR ; EXIT=$?
rm -f $OUT $ERR
wait

echo "I: Finished with exitcode $EXIT"

exit $EXIT

Вы можете проверить это с помощью ./this_script another_scriptили command.

coffeMug
источник
1

Я постараюсь проанализировать следующую часть вашего вопроса:

вместо этого будет выглядеть примерно так:

 ~ $ какая-то команда
 некоторая полезная информация о выходе |
 больше выхода | ОШИБКА: ошибка
 другое сообщение | ОШИБКА: произошло
 ~ $ 

Если кто-то хочет разбить то, что вы хотите:

1) stdoutПоток не заканчивал бы каждую строку символом «а», CR LFа вместо этого символом «|» персонаж. Это, конечно, не выровняло бы два потока вместе, и о выравнивании не может быть и речи, потому что это должно было бы предсказать длину будущих линий, добавленных к stdout, что, конечно, невозможно.

2) Предполагая, что мы забыли о выравнивании, мы просто вывели бы stderrпосле обработки конвейером, который добавляет «ОШИБКА:» в начало каждой строки. Я полагаю, что это довольно легко сделать простым сценарием и убедиться, что stderrэтот сценарий всегда работает.

Но это создало бы вывод как это:

~ $ какая-то команда
 некоторая полезная информация о выходе |
 больше выхода | ОШИБКА: ошибка
 другое сообщение | ОШИБКА: произошло

Что не очень полезно, не так ли? Также я не верю, это то, что вы после тоже!

Проблема с начальным вопросом, я думаю, заключается в том, что вы не учитываете последовательный характер каждой строки, добавляемой в поток, в связи с тем, что оба потока могут быть записаны асинхронно.

Я считаю, что наиболее близким решением будет использование ncurses.
Видеть.
[ http://www.tldp.org/HOWTO/html_single/NCURSES-Programming-HOWTO/]
[ http://invisible-island.net/ncurses/ncurses-intro.html#updating]

Чтобы сделать то, что вам нужно, вам нужно буферизовать оба потока и объединить их, чтобы создать третий буфер, который получает элементы из обоих буферов. Затем сбросьте третий буфер в экран терминала, стирая экран терминала и перерисовывая его каждый раз, когда третий буфер изменяется. Но этот способ ncursesработает, так зачем изобретать велосипед, а не брать его оттуда?
В любом случае, вы должны были бы полностью изменить цвет экрана терминала ! И выровняйте текст в перепечатанной версии экрана, как вам нравится. Очень похоже на видеоигру с терминальными персонажами.
Я надеюсь, что мой ответ поможет прояснить ограничения того, что вы после ...
Простите за повторение этого , но самая большая проблема с тем, что вы показали, как будет выглядеть «процессор» из stdoutи stderrпотоки заранее знать длину линий будущих добавленных к нему для того , чтобы выровнять их должным образом.

Ангелос Асонит
источник