Відображати stdout та stderr у двох окремих потоках


13

Я шукаю спосіб візуально розділити 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
Kusalananda

Чи корисна утиліта анотації-виводу виглядає корисною, чи вам потрібен вихід у стовпцях?
Джефф Шаллер

Відповіді:


5

Ви можете використовувати 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.


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потоки заздалегідь знатимуть довжину доданих до нього майбутніх рядків, щоб правильно їх вирівняти.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.