Мабуть багато-хто якось думав, що було б непогано наділити власний скрипт графічним інтерфейсом. Навіщо він потрібен - це вже інше питання: наприклад, для людей, далеких від консольних програм, користування псевдографічним інтерфейсом буде зрозумілішим чи просто таким чином скрипт буде виглядати дещо професійніше або ж ви лише думаєте, що він необхідний - а насправді це просто марнування часу. Для реалізації таких простих інтерфейсів будемо використовувати програму dialog (ncurses-інтерфейс) та shell.
Звісно програму необхідно спочатку встановити:
# aptitude install dialog
Продемонструю його роботу з найпростішим case-скриптом.
#!/bin/bash
dialog --title 'Перезапуск мережі' \
--yesno "Ви насправді бажаєте перезавантажити сервіс мережі на комп'ютері?" 10 40
case "$?" in
'0')
sudo service networking restart > /dev/null &2>1
echo 'Restarting...'
;;
'1')
exit 0
;;
-1|255)
echo "Сталась помилка, або ви натиснули ESC"
esac
Ключем "-yesno" вказуємо програмі dialog створити вікно з вибором "Так" чи "Ні", "--title" - встановлює назву вікна. Відповідь, що була обрана буде ідентифікуватись зі змінної $? (код завершення останньої команди). Тобто dialog буде повертати "0", якщо було обрано "Yes" та "1" - якщо "No". "10 40" - це позиція вікна, можна указати дефолтні - "0 0".
Також dialog повертає код "-1" у випадку, коли сталась помилка та "255", якщо було натиснено клавішу ESC.
У наступному прикладі буде продемонстровано вивід вікна, де користувач може самостійно ввести програму, що хоче запустити:
#!/bin/bash
TMPFFCMD="/tmp/cmd.tmp"
dialog --title 'Execute command' --inputbox 'Уведіть програму, яку хочете запустити:' 10 40 'ls' 2> $TMPFFCMD
CMD2RUN=$(cat $TMPFFCMD)
if [ "$?" -ne "-1" ]; then
$CMD2RUN
else
echo "Отримано код -1 від dialog"
fi
rm -f $TMPFFCMD
Параметр "--inputbox" призводить до появи вікна введення, де 'ls' буде вказана, як дефолтна програма. Вибір програми через stderr буде перенаправлено в змінну $TMPFFCMD. У випадку появи помилки буде виведено відповідне повідомлення.
Тепер створимо діалогове меню вибору програм на ncurses:
#!/bin/bash
TMPFCMD="/tmp/cmd.tmp"
dialog --title 'Execute command' --menu 'Оберіть програму для запуску' 0 0 0 \
l 'ls -la' \
p pwd \
d date \
u 'uname -a' \
w whoami 2> $TMPFCMD
CMD2RUN=$(cat $TMPFCMD)
if [ "$?" -eq "0" ]; then
case "$CMD2RUN" in
"l")
ls -la
;;
"p")
pwd
;;
"d")
date
;;
"u")
uname -a
;;
"w")
whoami
;;
esac
fi
rm -f $TMPFCMD
Кожна програма супроводжується тегом в меню dialog, котрий буде записуватись в $TMPFCMD після вибору відповідного пункту в меню. Власне від записаного тегу і буде залежати яку програму буде запущено.
Останній тип діалогових вікон не запитує в користувача жодних данних, а лиш надає певну інформацію користувачу. Їх роботу продемонструємо на такому прикладі:
#!/bin/bash
dialog --title 'Infoboxes script' --infobox "Цей скрипт не виконує жодної корисної роботи, він просто демонструє роботу інформаційних діалогових вікон" 10 50
sleep 2
{
i=0
while [ "$i" -lt "110" ]; do
sleep 0.25
echo $i
let "i += 10"
done; sleep 1; } | dialog --title 'Infoboxes script' --gauge 'Перебіг процесу' 10 50 0
dialog --title 'Infoboxes script' --infobox 'Скоро скрипт завершиться...' 10 50
sleep 2
dialog --title 'Infoboxes script' --msgbox 'Будь ласка, натисніть OK' 10 50
dialog --title 'Infoboxes script' --pause 'Пауза' 10 50 5
Спершу виводиться діалогове інформаційне вікно (опція "--infobox"), надалі - смуга завантаження ("--gauge") та пауза ("--pause"). Зауважу що для відображення рівня завантаження необхідно передавати (через пайп, як в скрипті вище) dialog-у число рівня завантаження.
Накінець розглянемо комплексний скрипт з використанням всіх вищезгаданих моживостей утиліти dialog. Створимо файл /tmp/conf.txt з таким змістом:
port:3322
threads:2
logdir:/opt/user6/logs/
confdir:/opt/user6/etc/
Скрипт матиме можливість редагувати значення цього файлу за допомогою awk і буде виглядати так:
#!/bin/sh
#автор http://unstableme.blogspot.com/
#Розміщення файлу, що буде редагуватись та опис тимчасових файлів для вікон dialog.
file=/tmp/conf.txt
tempfile1=/tmp/dialog_1_$$
tempfile2=/tmp/dialog_2_$$
tempfile3=/tmp/dialog_3_$$
#Перехоплення системних викликів. Видалення тимчасових файлів у разі надсилання процесу відповідних сигналів.
tempfile1=/tmp/dialog_1_$$
tempfile2=/tmp/dialog_2_$$
tempfile3=/tmp/dialog_3_$$
#Перехоплення системних викликів. Видалення тимчасових файлів у разі надсилання процесу відповідних сигналів.
trap "rm -f $tempfile1 $tempfile2 $tempfile3" 0 1 2 5 15
#Опис функції _edit()
#Опис функції _edit()
_edit () {
items=$(awk -F\: '{print $1,$2}' $file)
items=$(awk -F\: '{print $1,$2}' $file)
#Вивід меню із пропозицією редагування відповідних файлу conf.txt.
dialog --title "A Sample Application" \
--menu "What you want to change :" 0 0 0 $items 2> $tempfile1
retval=$?
parameter=$(cat $tempfile1)
#Якщо код виконання останньої команди рівний 0 - присвоїти значення змінної $parameter змінній $tochange. Інакше - поповернути 1.
dialog --title "A Sample Application" \
--menu "What you want to change :" 0 0 0 $items 2> $tempfile1
retval=$?
parameter=$(cat $tempfile1)
#Якщо код виконання останньої команди рівний 0 - присвоїти значення змінної $parameter змінній $tochange. Інакше - поповернути 1.
[ $retval -eq 0 ] && tochange=$parameter || return 1
# awk виводить значення другого стовпчика, якщо значення першого рівне x(змінна tochange).
val=$(awk -F\: -v x=$tochange '$1==x {print $2}' $file)
echo $val > tmp.log
#Діалог зміни необхідного параметру файлу conf.txt
dialog --clear --title "Inputbox - Test" \
--inputbox "Enter new value($tochange)" 0 0 $val 2> $tempfile2
#Діалог, що запитує чи наспраді ми хочемо змінити значення dialog --title "Confirmation" --yesno "Commit ?" 0 0
case $? in
0) newval=$(cat $tempfile2)
# awk змінює значення на n($newval) у разі якщо значення у першому стовпчику буде рівне x($tochange)
awk -v x=$tochange -v n=$newval '
BEGIN {FS=OFS=":"}$1==x {$2=n} {print}
' $file > $file.tmp
mv $file.tmp $file
;;
1|255) dialog --infobox "No Changes done" 0 0
sleep 2
;;
esac
dialog --textbox $file 0 0
}
# Функція виведення першого основного вікна з пунктами меню
_main () { dialog --title "A sample application" \
--menu "Please choose an option:" 15 55 5 \
1 "View the config file" \
2 "Edit config file" \
3 "Exit from this menu" 2> $tempfile3
retv=$?
choice=$(cat $tempfile3)
#Аналізується код повернення команди dialog: якщо код виконання останньої команди 1 чи 255(клавіша ESC) - вихід
[ $retv -eq 1 -o $retv -eq 255 ] && exit
#Запуск вищеописаних функцій залежно від вибору
case $choice in
1) dialog --textbox $file 0 0
_main
;;
2) _edit
_main ;;
3) exit ;;
esac
}
--menu "Please choose an option:" 15 55 5 \
1 "View the config file" \
2 "Edit config file" \
3 "Exit from this menu" 2> $tempfile3
retv=$?
choice=$(cat $tempfile3)
#Аналізується код повернення команди dialog: якщо код виконання останньої команди 1 чи 255(клавіша ESC) - вихід
[ $retv -eq 1 -o $retv -eq 255 ] && exit
#Запуск вищеописаних функцій залежно від вибору
case $choice in
1) dialog --textbox $file 0 0
_main
;;
2) _edit
_main ;;
3) exit ;;
esac
}
#Скрипт стартує з запуску функції _main
_main
Посилання:
http://www.unixcl.com/2009/12/linux-dialog-utility-short-tutorial.html
http://www.ibm.com/developerworks/ru/library/l-dialog/
http://www.ibm.com/developerworks/ru/library/l-awk1/
http://www.thegeekstuff.com/2010/01/8-powerful-awk-built-in-variables-fs-ofs-rs-ors-nr-nf-filename-fnr/
_main
Як помітно з коментарів до коду, на виході буде отримано новий файл зі зміненим значенням навпроти необхідного параметру. Якщо маєте питання чи просто помітили помилку - ласкаво прошу в коментарі.
Посилання:
http://www.unixcl.com/2009/12/linux-dialog-utility-short-tutorial.html
http://www.ibm.com/developerworks/ru/library/l-dialog/
http://www.ibm.com/developerworks/ru/library/l-awk1/
http://www.thegeekstuff.com/2010/01/8-powerful-awk-built-in-variables-fs-ofs-rs-ors-nr-nf-filename-fnr/
Немає коментарів:
Дописати коментар