Интересные идеи были даны здесь для этого сложного вопроса, но я не видел никакого полного решения до сих пор. Я постараюсь дать один. Чтобы достичь этого, я сначала написал три сценария, соответствующих конвейеру prog1 | prog2 | prog3
, о котором говорил PO.
prog1 , производящий сообщения, разделенные \n
в потоке ошибок, и генерирующий числа в стандартном потоке:
#!/bin/bash
cmd=$(basename $0)
seq 8 |
while ((i++ < 10)); do
read line || break
echo -e "$cmd: message $i to stderr" >&2
echo $line
sleep 1
done
echo -e "$clearline$cmd: has no more input" >&2
prog2 , создающие сообщения, разделенные \r
, и перезаписывают свой собственный вывод в потоке ошибок и передают числа из стандартного входного потока в стандартный выходной поток :
#!/bin/bash
cmd=$(basename $0)
el=$(tput el)
while ((i++ < 10)); do
read line || break
echo -en "$cmd: message $i to stderr${el}\r" >&2
echo $line
sleep 2
done
echo -en "$clearline$cmd: has no more input${el}\r" >&2
и, наконец, prog3 чтение из стандартного потока ввода и запись сообщений в поток ошибок таким же образом, как prog2
:
#!/bin/bash
cmd=$(basename $0)
el=$(tput el)
while ((i++ < 10)); do
read line || break
echo -en "$cmd: message $i to stderr${el}\r" >&2
sleep 3
done
echo -en "$clearline$cmd: has no more input${el}\r" >&2
Вместо вызова этих трех сценариев как
prog1 | prog2 | prog3
Нам понадобится сценарий для вызова этих трех программ, перенаправляющих поток ошибок в три специальных файла FIFO (именованные каналы), но перед запуском этой команды нам придется сначала создайте три специальных файла и запустите в фоновом режиме прослушивание специальных файлов: каждый раз полная строка будет отправлена, этот процесс напечатает ее в специальной области экрана, которую я назову панелью задач.
Три панели задач находятся внизу экрана: верхняя будет содержать сообщения prog1
потоку ошибок, следующий будет соответствовать prog2
, а последний внизу будет содержать сообщения от prog3
.
В конце, файлы FIFO должны быть удалены.
Теперь хитрые части:
- Я не нашел утилиты для чтения без буферизации строки, заканчивающейся на
\r
, поэтому мне пришлось изменить \r
на \n
перед выводом строк сообщений на экран; - некоторые программы в нескольких программах, которые я подключал к каналам, буферизировали их ввод или вывод, вызывая сообщения не должны быть напечатаны до конца, что явно не является предполагаемым поведением; для исправления этого я должен был использовать команду
stdbuf
с утилитой tr
;
Собрав все вместе, я реализовал следующий скрипт, который работает, как и предполагалось:
#!/bin/bash
echo -n "Test with clean output"
echo;echo;echo # open three blank lines in the bottom of the screen
tput sc # save the cursor position (bottom of taskbars)
l3=$(tput rc) # move cursor at last line of screen
l2=$(tput rc; tput cuu1) # move cursor at second line from bottom
l1=$(tput rc; tput cuu1; tput cuu1) # move cursor at third line from bottom
el=$(tput el) # clear to end of line
c3=$(tput setaf 1) # set color to red
c2=$(tput setaf 2) # set color to green
c1=$(tput setaf 3) # set color to yellow
r0=$(tput sgr0) # reset color
mkfifo error{1..3} # create named pipes error1, error2 and error3
(cat error1 | stdbuf -o0 tr '\r' '\n' |
while read line1; do echo -en "$l1$c1$line1$el$r0"; done &)
(cat error2 | stdbuf -o0 tr '\r' '\n' |
while read line2; do echo -en "$l2$c2$line2$el$r0"; done &)
(cat error3 | stdbuf -o0 tr '\r' '\n' |
while read line3; do echo -en "$l3$c3$line3$el$r0"; done &)
./prog1 2>error1 | ./prog2 2>error2 | ./prog3 2>error3
wait
rm error{1..3} # remove named pipes
tput rc # put cursor below taskbars to finish gracefully
echo
echo "Test finished"
Мы добавили цвета, разные для каждой строки панели задач, со строками, созданными tput
.
Наслаждайтесь.