Вопрос или проблема
У меня есть скрипт, который запускает около 10 других скриптов в фоновом режиме, которые постоянно генерируют новый вывод. Я хотел бы, чтобы этот начальный скрипт продолжал работать, и иметь возможность просто вводить в него, чтобы фильтровать весь вывод, отображаемый в терминале в реальном времени.
Для упрощения допустим, что каждый из этих циклов for представляет один из моих фоновых скриптов (вывод содержит цветовые коды, кстати):
for i in {0..1000} ; do
echo -e "\033[0;31mПривет мир\033[0m $i"
sleep 1
done &
for i in {0..1000} ; do
echo -e "\033[0;34mПривет мир\033[0m $i"
sleep 1
done &
Моя первая идея заключалась в том, чтобы перенаправить весь вывод фоновых скриптов в файл, а затем использовать команду read
для получения поискового запроса и передачи его в grep
вот так:
for i in {0..1000} ; do
echo -e "\033[0;31mПривет мир\033[0m $i"
sleep 1
done >> ./output.txt 2>&1 &
for j in {0..1000} ; do
echo -e "\033[0;34mПривет мир\033[0m $j"
sleep 1
done >> ./output.txt 2>&1 &
while true ; do
read -p "Поиск: " query
clear
cat ./output.txt | grep "$query"
done
Но с этим есть несколько проблем.
Проблема обновления: Вывод не обновляется, когда файл output.txt
изменяется. Поэтому вам нужно снова делать поиск, чтобы получить актуальные результаты.
Проблема цветового кода: Если я ищу 3
, он выведет все строки, потому что цветовые коды содержат 3
. Я мог бы, конечно, полностью отфильтровать цвета вот так: cat ./output.txt | sed 's/\x1b\[[0-9;]*m//g' | grep "$query"
, но я не хочу терять цвет в финальном выводе, так что это не так просто.
Проблема исчезающего ввода: Даже если мне удастся заставить новый вывод печататься в реальном времени после нажатия Enter для поиска, пользователь не сможет нормально ввести (или видеть, если быть более точным) свой следующий поиск. Я хотел бы, чтобы текст фильтра, который вводит пользователь, всегда был виден.
Есть идеи, как это можно реализовать?
less -R
Вы можете использовать просмотрщик less
, чтобы
- увидеть ANSI цвета с опцией
-R
- искать вперед по
шаблону
с помощью/шаблон
-
искать назад по
шаблону
с помощью?шаблон
-
Навигация с помощью клавиш стрелка и PgUp, PgDn, Home, End.
- Обратите внимание, что ваш буфер обновляется, когда вы нажимаете End 🙂
- Проблема цветового кода решена.
- Ввод не исчезает.
Используйте следующий скрипт для записи,
#!/bin/bash
for i in {0..1000} ; do
echo -e "\033[0;31mПривет мир\033[0m $i"
sleep 1
done >> output.txt 2>&1 &
for j in {0..1000} ; do
echo -e "\033[0;34mПривет мир\033[0m $j"
sleep 1
done >> output.txt 2>&1 &
Используйте эту командную строку для чтения/проверки,
less -R output.txt
Shellscript с fifo
, tail
и grep
Альтернативой простой команде less
является следующий небольшой shellscript. Предполагается, что вы можете прокручивать достаточно в окне терминала, чтобы видеть и старый вывод. Возможно увеличить буфер, если он недостаточно велик. У меня есть следующие строки в моем `.bashrc`, и я думаю, что они делают то, что вам нужно для этой цели,
HISTFILESIZE=1000000
HISTSIZE=10000
Shellscript для фильтрации и проверки,
#!/bin/bash
# эта функция вызывается, когда отправляется Ctrl-C ##########################
inversvid="\0033[7m"
resetvid="\0033[0m"
function trap_ctrlc ()
{
# выполнить очистку здесь
echo " Нажмите <Enter> для продолжения с другим запросом или"
echo -en "$inversvid"
read -s -n1 -t5 -p " <x> для выхода " ans
echo -en "$resetvid"
if [ "$ans" == "x" ]
then
# выйти из shellscript
# если пропустить, shellscript продолжит выполнение
echo ""
exit
else
echo ""
fi
}
##### main #############################################################
# инициализация ловушки для вызова функции trap_ctrlc
# когда сигнал 2 (SIGINT) получен
trap "trap_ctrlc" 2
echo "Прокрутите окно терминала (возможно, увеличьте буфер, чтобы сохранить достаточно строк)
Прервите просмотр отфильтрованного вывода с помощью <ctrl c>"
if [ "$1" == "" ]
then
read -p "Поиск: " query
else
query="$@"
fi
# создать fifo
mkfifo fifo
# запуск цикла для запросов и отфильтрованного вывода
while true ; do
if [ "$query" == "" ]
then
read -p "Новый поиск: " query
fi
# mkfifo fifo
clear
tail -n 10000 -f output.txt > fifo &
grep --color -E "$query" fifo
sleep 0.1
query=""
done
Пожалуйста, обратите внимание, что этот shellscript будет видеть также ANSI escape последовательности, поэтому, например, если вы хотите фильтровать по 0
, вы увидите все строки (потому что есть ноль в сбросной последовательности). Вы можете использовать расширенные регулярные выражения (опция -E
в grep
, которые позволяют указать, что вы хотите искать, например \ .?0
или0$
.
(Это не является проблемой с less -R
).
Ответ или решение
Для решения вашей задачи по фильтрации вывода скриптов во время их выполнения в реальном времени, можно использовать несколько подходов. Рассмотрим наиболее эффективные из них: использование утилиты less
с поддержкой ANSI-кодов и создание скрипта на Bash с использованием FIFO, tail
и grep
.
Использование less -R
Утилита less
позволяет просматривать текстовые файлы с поддержкой цветовых кодов ANSI и предоставляет возможности для поиска. Вы можете использовать ее так:
- Создайте основной скрипт для генерации вывода:
#!/bin/bash
for i in {0..1000}; do
echo -e "\033[0;31mHello world\033[0m $i"
sleep 1
done >> output.txt 2>&1 &
for j in {0..1000}; do
echo -e "\033[0;34mHello world\033[0m $j"
sleep 1
done >> output.txt 2>&1 &
- Для просмотра выходных данных с возможностью поиска выполните следующую команду в терминале:
less -R output.txt
Используйте /
для поиска вперед и ?
для поиска назад. Таким образом, вы сможете видеть обновления в реальном времени без потерь цветового оформления.
Скрипт с использованием FIFO, tail
и grep
Если вы хотите более интерактивный подход, вы можете создать скрипт, который будет запускать tail
и фильтровать вывод с помощью grep
в реальном времени. Вот пример такого скрипта:
#!/bin/bash
inversvid="\033[7m"
resetvid="\033[0m"
function trap_ctrlc {
echo " Нажмите <Enter> для продолжения с новым запросом или"
echo -en "$inversvid"
read -s -n1 -t5 -p " <x> для выхода " ans
echo -en "$resetvid"
if [ "$ans" == "x" ]; then
echo ""
exit
else
echo ""
fi
}
trap "trap_ctrlc" 2
echo "Прокрутите окно терминала. Для выхода нажмите Ctrl+C."
mkfifo fifo
while true; do
read -p "Введите строку для поиска: " query
clear
tail -n 10000 -f output.txt > fifo & # Запуск tail в фоне
grep --color -E "$query" fifo # Фильтрация результата
sleep 0.1
done
Примечания
- Использование
less -R
является простым решением и позволяет сохранить цветовой вывод, а также предоставляет возможность прокрутки и поиска. - Скрипт с использованием FIFO позволяет более интерактивно взаимодействовать с пользователем, однако вводимые команды для поиска будут также иметь свои сложности, например, возможно, придется использовать регулярные выражения для точного поиска.
Рекомендации
- Убедитесь, что ваш терминал настроен на поддержку ANSI-кодов.
- Проверьте буфер терминала — возможно, потребуется увеличить его размер для хранения достаточного количества строк вывода.
- Экспериментируйте с регулярными выражениями в
grep
для точного поиска по цветному выводу.
Эти методы позволяют эффективно организовать вывод и фильтрацию в реальном времени без потери цветового оформления, что является важным для визуального восприятия.