Отображение stdout и stderr в двух отдельных потоках.

как разделить stdout и stderr

Вопрос или проблема

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

~$ какая-то команда

какая-то полезная информация

ОШИБКА: ошибка

дополнительный вывод

ОШИБКА: произошло

еще одно сообщение

~$

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

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

~$ |

Вы могли бы использовать вертикальное разделение в GNU screen:

#! /bin/bash -tmpdir=$(mktemp -d) || exittrap ‘rm -rf «$tmpdir»‘ EXIT INT TERM HUPFIFO=$tmpdir/FIFOmkfifo «$FIFO» || exitconf=$tmpdir/confcat > «$conf» << ‘EOF’ || exitsplit -vfocusscreen -t stderr sh -c ‘tty > «$FIFO»; read done < «$FIFO»‘focusscreen -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»‘EOFCMD=»$*»

export FIFO CMDscreen -mc «$conf»

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

that-script ‘ls / /not-here’

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

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

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

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

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

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

#!/bin/bash

readonly col=150 # столбец для начала вывода ошибокa

dd_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: %sn» $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/outERR=$tmp/errmkfifo $OUT $ERR || exit 1

add_out OUTPUT < $OUT &add_err ERROR < $ERR &echo «I: Начало выполнения $@»»$@» > $OUT 2> $ERR ;

EXIT=$?

rm -f $OUT $ERRwaitecho «I: Завершено с кодом выхода $EXIT»exit $EXIT

Вы можете протестировать это, используя ./this_script another_script или command.

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

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

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

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

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

Я был поражён, что под Linux нет идеальной команды для этого, поэтому я написал небольшую утилиту на Python:

# output.py

import sysfrom rich

import printfrom rich.panel

import Panelimport subprocess

result = subprocess.run( sys.argv[ 1: ], capture_output = True, text = True )

print( Panel( result.stdout ) )

print( Panel( result.stderr ) )

Выглядит это так:

$ output.py какая-то команда

╭──────────────────────────────────────╮│ …stdout… │╰──────────────────────────────────────╯╭──────────────────────────────────────╮│ …stderr… │╰──────────────────────────────────────╯

Зависит от пакета rich.

Ответ или решение

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

Теория

Главная идея заключается в том, чтобы визуально разделить потоки stdout и stderr. Решение этой задачи связано с пониманием того, как данные выводятся в терминале. Обычно, терминал смешивает оба потока, что может привести к неупорядоченному выводу, особенно если программа активно использует оба потока.

Разделяя выводящие потоки визуально, мы можем легко идентифицировать и устранить ошибки. Это достигается путем направления каждого потока в отдельную область экрана или в разные логические потоки в пользовательском интерфейсе. Два подхода, которые могут быть использованы для этого, включают использование программных оболочек, таких как GNU Screen, и написание пользовательских скриптов с использованием направляющих символов (pipes) и временных файлов.

Пример

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

#! /bin/bash

-tmpdir=$(mktemp -d) || exittrap ‘rm -rf «$tmpdir»‘ EXIT INT TERM HUPFIFO=$tmpdir/FIFO

mkfifo «$FIFO» || exitconf=$tmpdir/confcat > «$conf» << ‘EOF’ || exitsplit -vfocusscreen -t stderr sh -c ‘tty > «$FIFO»;

read done < «$FIFO»‘

focusscreen -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»‘EOFCMD=»$*»

export FIFO CMD

screen -mc «$conf»

Данный скрипт создает временные файловые каналы и конфигурационный файл для screen. В конфигурационном файле настроено вертикальное разделение окна, в котором одна половина отображает stdout, а другая – stderr.

Применение

Для минимизации смешивания данных выходного потока и ошибок программное обеспечение или команды должны быть запущены через скрипт, предлагающий альтернативные пути вывода для каждого потока. Например, подключив данный скрипт к команде ls или другой команде, которая генерирует достаточно вывода и ошибок, можно четко увидеть распределение данных между двумя экранами.

Еще один подход заключается в написании скриптов на Python с использованием библиотек, таких как Rich. Пример на Python иллюстрирует возможность использования этого подхода:

# output.py

import sysfrom rich

import printfrom rich.panel

import Panelimport subprocess

result = subprocess.run( sys.argv[ 1: ], capture_output=True, text=True)

print(Panel(result.stdout))

print(Panel(result.stderr))

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

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

Друзья помогите этому контенту стать доступнее в социальных сетях.

Не проходи мимо жмакни по кнопке возможно кому то еще он будет полезен!