Толик Панков
hex_laden
............ .................. ................
  Viewing 0 - 7  
Linux dialog --tailbox

tailbox - интересный виджет программы dialog, позволяющий видеть дополнения в текстовом файле в реальном времени, что делает его удобным для отображения логов



Прямая ссылка: https://youtu.be/kdOjJFtbuI4

Если переданный программе лог не дополняется, то tailbox просто отображает последние строки из файла (насколько хватает заданных размеров виджета)



Вызов виджета:

dialog --title "заголовок_окна"  \
	  --exit-label "Надпись_на_кнопке_выхода" \
       --tailbox "текстовый_файл" высота ширина


Например:

dialog --title "LOG"  \
	  --exit-label "Close log window" \
       --tailbox "/tmp/mylog.log" 24 70


Для демонстрации написал простой log viewer.
Использование:

logview путь_к_файлу

logview )

Скрипт на GitHub

Отправка лога одновременно на дополнительный терминал, в файл и отображение в tailbox'е


Вроде бы виджет простой, но при некоторой смекалке можно делать интересные вещи, например, вести лог сразу в трех местах - отображая его в --tailbox'е, одновременно отправляя изменения, происходящие в реальном времени на отдельный терминал, и сохраняя лог в файл (с перезаписью или дозаписью)



Прямая ссылка https://youtu.be/AARNx4SbYJg

Добиться этого можно, совместив dialog tailbox с командой tee (копия).

Написал демонстрационный скрипт:
Демонстрационный скрипт )

В качестве источника логов, демо-скрипт вызывает в фоновом режиме другой скрипт tscript, который выводит 10 случайных чисел на консоль и завершает работу:

#!/bin/bash

SEC=1
CTR=10

echo "Test script, write to STDOUT random number after $SEC sec."

while [ "$CTR" -ne 0 ];do
    let "CTR=CTR-1"
    printf '%x Number: %x\n' $CTR $RANDOM
    sleep $SEC
done

echo "Complete!"


Настройки скрипта для поиграться можно провести через внутренние переменные:

LOG_FILE="./test.log" - если значение не задано, создается временный файл, который по завершению скрипта удаляется.
LOG_TTY="/dev/tty4" - если значение не задано, лог в реалтайме не отправляется на дополнительный терминал
RMLOG=0 - 0 - по завершению скрипта лог не удаляется, 1 - удаляется.
LOG_APPEND=1 - 0 - при каждом запуске создается новый файл. 1 - добавление данных в лог, если он существует.

Скрипты на GitHub

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2020/10/25/linux-dialog-tailbox/

Tags: , ,
Linux shell, pipes (конвейеры) и код завершения.

Преамбула


При работе с конвейерами (пайпами, "трубами", pipe), часто возникает вопрос, как отловить ошибку, произошедшую внутри конвейера.

Суть проблемы


Для примера возьмем код, где ход загрузки файла отображается dialog'овым прогрессбаром (копия):

#!/bin/bash

FADDR="http://tolik-punkoff.com/static/test.mp3"

wget --progress=dot -O "./test.mp3" "$FADDR" 2>&1 |\
stdbuf -o0 awk '/[.] +[0-9][0-9]?[0-9]?%/ { print substr($0,63,3) }' | \
dialog --gauge "Download file from $FADDR" 10 100


Как видите, конвейер (т.е. передача вывода от одной команды другой через |), тут налицо.

Если после данной команды просто дописать echo $?, то будет видно, что результат будет 0.

И когда все в порядке:



И когда все не в порядке (в данном случае, сделан обрыв связи):



На самом деле, это происходит потому, что в переменной $? оказывается код завершения последней команды в pipe.

Решение


В современных версиях bash перед использованием контейнера, необходимо добавить команду:

set -o pipefail

В старых bash и некоторых других оболочках придется извращаться, может как-нибудь вернусь к вопросу (если для какого утюга что писать буду).

Примечание: Следует иметь в виду “безобидные” команды, которые могут вернуть не ноль.
В больших скриптах со сложными конструкциями и длинными конвеерами можно упустить этот момент из виду, что может привести к некорректным результатам.


Проверка


После добавления вышеуказанной команды в скрипт делаем тест с обрывом связи:



Или указываем в переменной $FADDR некорректный адрес:



Теперь echo $? отображает корректный код завершения.

Модификация скрипта )

Скрипт на GitHub

Источник


Linux pipes tips & tricks Копия в PDF

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2020/02/20/linux-shell-pipes-konvejery-i-kod-zaversheniya/

Tags: , ,
Linux dialog --infobox с "мельницей", скрашивающей процесс ожидания.

Сделал гибрид старого скрипта waiter (копия) с dialog --infobox. В infobox'е отображается псевдографическая "мельница"



https://www.youtube.com/watch?v=o9KempHy5To

Не стал уж совсем дублировать waiter, так что никаких параметров демо-скрипт не принимает, просто отсчитывает 10 секунд, показывая псевдографическую "крутилку".

Исходник на GitHub

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2020/02/17/linux-dialog-infobox-s-melnitsej-skrashivayushhej-protsess-ozhidaniya/

Linux dialog, прикручиваем симпатичный progressbar к wget.

Преамбула


Какой бы ваш скрипт не был диалоговым, "само дерево жужжать не может", а в скрипте обычно жужжат утилиты, которые о диалоговых окнах представления не имеют. Так вот прикрутим контролируемый прогрессбар (--gauge) из виджетов dialog к всем известному wget.

Готовый код


#!/bin/bash

FADDR="http://tolik-punkoff.com/static/test.mp3"

wget --progress=dot -O "./test.mp3" "$FADDR" 2>&1 |\
stdbuf -o0 awk '/[.] +[0-9][0-9]?[0-9]?%/ { print substr($0,63,3) }' | \
dialog --gauge "Download file from $FADDR" 10 100



Разбираем, что он делает


1. Если просто запустить wget без параметра --progress=dot (параметр -O "./test.mp3" здесь показывает путь и имя для сохраняемого файла, для теста оно у нас жестко задано), то wget попытается нарисовать свой плохенький progressbar:



Использование параметра --progress=dot приводит вывод на экран в такой вид:



Теперь у нас видны проценты, которые выводятся по штуке на строчку через определенный интервал времени по внутреннему алгоритму wget.

2. wget почему-то выводит сообщения о своей работе не на stdout, а на stderr. Аж морово поветрие какое-то, ибо и некоторые другие утилиты тоже выводят на stderr. Оправданно на stderr выводит сообщения только dialog, тому ще он всю псевдографику выводит на stdout. Отучаем wget писать на stderr вместо stdout:

2>&1

2 - зарезервированный канал для stderr 1 - для stdout. Тут мы просто перенаправляем один канал в другой.

3. Меняем буферизацию. На самом деле, буфер консоли (терминала) выводит на экран сообщение, если в буфере консоли накопилось 1024 байта. Или программа завершилась. Иначе нет. С помощью утилиты stdbuf устанавливаем буфер stdout (-o) в ноль (-o0), тем самым мы добиваемся, чтоб символы сразу поступали на вход awk. stdbuf в качестве второго параметра требует программу, которой она будет посылать измененный буфер. В данном случае awk.

buffering in standard streams
man stdbuf на русском

За разъяснение спасибо другу из Телеграм.

4. Далее вывод wget'а передается awk, которая хитрой регуляркой и оператором substr вырезает из вывода все, кроме значений процентов.



5. dialog --gauge может принимать из stdout числа, и отображать их в виде progressbar'а



Пример на GitHub

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2020/02/05/linux-dialog-prikruchivaem-simpatichnyj-progressbar-k-wget/

Tags: , ,
Linux dialog --menu. Динамическое меню и прочие штуки

Динамическое меню из массива


dialog был бы совсем негибким инструментом, если бы не было возможности формировать элементы меню более-менее "налету", а не только непосредственно в коде скрипта. И такая возможность есть. Виджет --menu (а также --checklist и --radiolist, которые я здесь упущу), принимают на вход массив. Формат массива такой:

MNUARR[0]="Элемент 1"
MNUARR[1]="Описание 1"
MNUARR[2]="Элемент 2"
MNUARR[3]="Описание 2"
...

т.е. линейный массив, где в первый элемент записывается, извиняюсь за тавтологию, элемент, а в следующий - описание, далее все повторяется.

Массив будем брать из файла.

1. Определяем переменную с путем к файлу и массив:

MNUFILE="./dynmenu01.txt"
declare -a MNUARR


2. Заполняем массив:

IDX=0
while read LINE; do
    PT_1=`echo "$LINE"|awk '{print $1}'`
    PT_2=`echo "$LINE"|awk '{print $2}'`
    MNUARR[$IDX]=$PT_1
    let "IDX=IDX+1"
    MNUARR[$IDX]=$PT_2
    let "IDX=IDX+1"
done <"$MNUFILE"


3. Вызываем dialog:

dialog --clear \
    --title "Dynamic menu" \
    --menu "Select option:" \
    20 76 10 \
    "${MNUARR[@]}"




Пример на GitHub
Файл к нему

Меню из файла


Массивом, на самом деле, пользоваться неудобно, и код получается более громоздкий, и несовместимо это может оказаться с другими shell'ами, и возможностей у массива меньше. Есть другой выход - воспользоваться файлом специального формата. Для виджета --menu формат таков:

"Элемент 1"[пробел]"Описание 1"[пробел]\
"Элемент 2"[пробел]"Описание 2"[пробел]\


Собственно, от описания меню в коде ничем не отличающийся. Можно даже в одну строчку через пробелы все написать, но с пробелом и \ в конце строки симпатичнее.

Остается в параметре --file виджета --menu указать путь к файлу.

MNUFILE="./dynmenu-file.txt"

dialog --clear \
    --title "Dynamic menu" \
    --menu "Select option:" \
    20 76 10 \
    --file "$MNUFILE" \




Пример на GitHub
Файл к нему

Дополнительное описание (помощь) к элементу меню


С помошью общего для dialog ключа --item-help можно добавить к элементам подсказку, появляющуюся в выделенной строке внизу экрана. Подсказка ограничена количеством символов в строке, что не влезло - уползает за экран.

Формат файла для такого меню будет:

"Элемент 1"[пробел]"Описание 1"[пробел]"Помощь 1"[пробел]\
"Элемент 2"[пробел]"Описание 2"[пробел]"Помощь 1"[пробел]\


Точно также меню с помощью описывается и непосредственно в коде скрипта.

Вызов dialog:

MNUFILE="./dynmenu-file-help.txt"

dialog --clear \
    --item-help \
    --title "Dynamic menu" \
    --menu "Select option:" \
    20 76 10 \
    --file "$MNUFILE" \


Для динамического меню из массива это не работает (или я не понял как).



Пример на GitHub
Файл к нему

Разделители, или отображение небольших табличных данных в меню


Конечно, виджет --menu, это вам не DataGridView из .NET Framework, и вообще, отдельного виджета для отображения табличных данных у dialog нет, но, если данных немного, то можно воспользоваться общим параметром для виджетов dialog
--column-separator. Раз параметр общий, то кроме --menu, должен срабатывать и для --checklist и --radiolist.
После параметра --column-separator задаем, собственно, сам разделитель (в примере |).

Примечание: параметр работает только для описаний пунктов меню.

MNUFILE="./dynmenu-file-sep.txt"

dialog --clear \
    --item-help \
    --column-separator "|" \
    --title "Dynamic menu" \
    --menu "Select option:" \
    20 76 10 \
    --file "$MNUFILE" \




Пример на GitHub
Файл к нему

Эта опция работает и для динамического меню, созданного с помощью массива:

Пример на GitHub
Файл к нему

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2020/02/02/linux-dialog-menu-dinamicheskoe-menyu-i-prochie-shtuki/

Tags: , ,
Linux dialog --menu, пункт по умолчанию и сохранение выбранного элемента

Преамбула


dialog - консольная утилита, позволяющая встраивать в ваши скрипты псевдографический интерфейс. Есть и ее графические варианты Kdialog, Xdialog, позволяющие обеспечить ваши скрипты даже полноценным оконным интерфейсом в средах X-сервера.

Как пример можно привести скрипт пакетного переименования файлов (см. на GitHub) работающий в графической среде, или пакетный менеджер Slackware pkgtool.


pkgtool вид спереди


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

Примеры на GitHub

Общий синтаксис


Общий синтаксис утилиты dialog таков:

dialog <общие_параметры> <виджет> <параметры_виджета>

Пункт меню по умолчанию


Указание пункта меню по умолчанию возможен не только в виджете --menu, но и в других виджетах, потому прописать его надо в параметрах, указанных до вызова конкретного виджета.

Если будет указан несуществующий пункт меню или пустая строка, к ошибке это не приведет. Будет выбран первый пункт меню.

dialog --clear --title "Default Item Test" \
    --default-item "Item #2" \
    --menu "Select item:" \
    20 51 7 \
    "Item #1"  "Test Item #1" \
    "Item #2" "Test Item #2" \
    "Item #3" "Test Item #3" 2>"/tmp/dlgres.tmp"




Код на GitHub

Сохранение пункта меню и последующий его выбор


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

Но с помощью опции --default-item можно сделать так, чтоб при возврате в одно из меню выбирался последний выбранный пункт.

Сохранение последнего выбранного пункта меню в переменную


1. Заводим переменную для временного файла:

TEMPFILE="/tmp/dlgres.tmp"

2. И переменную для хранения пути к самой утилите dialog:

DIALOG="dialog"

Это не обязательно, но удобно, если понадобится переделать скрипт под Xdialog или Kdialog

3. Заводим переменную для последнего выбранного пункта:

LAST_MENU1=""

4. Само меню будем вызывать из функции menu_in_variable()

Далее внутри функции:

5. Заводим константы для кодов возврата программы dialog:

OK_C=0 #Нажата кнопка OK в диалоговом окне
ESC_C=255 #Нажата клавиша ESC
CANCEL_C=1 #Нажата кнопка Cancel в диалоговом окне


Примечание: На самом деле с отслеживанием клавиши ESC у утилиты menu какой-то конфликт с PuTTY, почему-то утилита завершает работу с кодом 255 не только по нажатию ESC, но и по нажатию клавиш F1..F4 Не в PuTTY это не проявляется.

5. Вызываем dialog:

$DIALOG --clear --title "Save last selected item into variable" \
    --default-item "$LAST_MENU1" \
    --menu "Select:" 20 60 7 \
    "Item #1" "Item 1" \
    "Item #2" "Item 2" \
    "Item #3" "Item 3" 2>"$TEMPFILE"


Примечание: dialog записывает в stderr выбранный элемент меню (в случае виджета --menu), потому перенаправляем вывод на stderr во временный файл, путь к которому указан в переменной $TEMPFILE (2>"$TEMPFILE")

6. Сохраняем код возврата:

RETVAL=$?

7. И далее его анализируем. Если нажата кнопка OK, то читаем файл с выбранным пунктом меню в переменную. Если нажата Cancel или клавиша ESC, то на stderr утилита ничего не выведет и временный файл будет пуст.

case "$RETVAL" in
	$OK_C)
		LAST_MENU1=`cat "$TEMPFILE" `
		#...
		;;
	$ESC_C)
		return;;
	$CANCEL_C)
		return;;
esac


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

Сохранение пункта меню в файл


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

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

STATEFILE="./savestate"

И перед вызовом dialog читаем файл в переменную:

if [ -e "$STATEFILE" ]; then
	LAST_MENU2=`cat "$STATEFILE"`
fi


Далее вызываем dialog, анализируем код возврата, и если что-то выбрано, копируем временный файл в файл для сохранения:

$DIALOG --clear --title "Save last selected item into file" \
	--default-item "$LAST_MENU2" \
    --menu "Select:" 20 60 7 \
    "Item #1" "Item 1" \
    "Item #2" "Item 2" \
    "Item #3" "Item 3" 2>"$TEMPFILE"

RETVAL=$?

case "$RETVAL" in
	$OK_C)
		cp "$TEMPFILE" "$STATEFILE"
		LAST_MENU2=`cat "$STATEFILE"`    
		;;
	$ESC_C)
		return;;
	$CANCEL_C)
		return;;
esac


Пример полностью на GitHub

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2020/02/02/linux-dialog-menu-punkt-po-umolchaniyu-i-sohranenie-vybrannogo-elementa/

Tags: , ,
Dialog - псевдографический оконный интерфейс в bash-скриптах

Оказывается, в bash-скриптах можно организовать псевдографический оконный интерфейс с помощью команды dialog. Не буду тут подробно про нее расписывать, потом покажу ее использование на реальном проекте, а пока заметка от склероза.

Краткий мануал на английском

Копия в PDF

Примеры скриптов на GitHub

Скачать в архиве

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2019/12/21/dialog-psevdograficheskij-okonnyj-interfejs-v-bash-skriptah/

Tags: , ,
  Viewing 0 - 7