Можно ли запустить диалог / сценарий whiptail в одном TTY из другого?
Происхождение этого вопроса, для меня, заключается в том, чтобы запустить команду Уиптейл в %pre
скрипт из файла кикстарта при установке пользовательского дистрибутива на основе Centos. Однако поведение, наблюдаемое в Anaconda, может быть легко воспроизведено через виртуальные терминалы любой системы Linux.
Для запуска команды Уиптейл в Анаконде в качестве кикстарта %pre
В скрипте необходимо переключить TTY и выполнить команду в этом новом TTY. Преобладающее предложение относительно того, как это сделать:
%pre
exec </dev/tty6 >/dev/tty6 2>/dev/tty6
chvt 6
# then execute your command, for example:
whiptail --inputbox "Enter some text..." 10 30
# switch back to the original TTY
chvt1
exec </dev/tty1 >/dev/tty1 2>/dev/tty1
%end
При использовании этого метода диалоговое окно whiptail корректно отображается в новом TTY, однако взаимодействие с диалогом невозможно, например, нажав tab
вместо переключения между элементами ввода текста, "ОК" и "Отмена" фактически вставляет вкладку в поле ввода текста. Точно так же использование клавиш со стрелками приводит к тому, что escape-последовательности записываются в диалоге:
Такое поведение также наблюдается при использовании python snack (использует ту же библиотеку, что и whiptail - libnewt) и диалоговом окне.
Конечно, я мог бы просто использовать интерактивный сценарий оболочки, а не использовать whiptail, но мне было просто интересно, есть ли у кого-нибудь какие-либо предложения относительно того, почему это поведение наблюдается, так как я бы подумал, что единственными требованиями для получения этой работы будут правильно перенаправить входной и выходной потоки.
TL; DR
Я заинтересован в создании сценария, содержащего команды whiptail/dialog, которые могут быть выполнены в одном TTY и получать / вводить сценарий в / из другого TTY.
2 ответа
Это сработало для меня (Anaconda, Fedora 20):
%pre --log=/tmp/ks_pre.log
#!/bin/bash
# Backup fds in temporal ones
exec {STDOUTBACK}>&1
exec {STDERRBACK}>&2
# Go to current terminal for pre% section
exec 1>>/dev/pts/0
exec 2>>/dev/pts/0
# Show message
whiptail --yesno 'Do you like StackOverflow?' --yes-button 'Yes' --no-button 'No' 10 70
if [ $? = 1 ]
then
echo 'User sucks' >> /tmp/ks_pre.log
else
echo 'User rocks' >> /tmp/ks_pre.log
fi
# Restore fds
exec 1>&$STDOUTBACK
exec 2>&$STDERRBACK
# Close temporal fds
exec {STDOUTBACK}>&-
exec {STDERRBACK}>&-
%end
Возможные вопросы:
Почему вы использовали
/dev/pts/0
?Потому что из консоли Anaconda я узнал, какое устройство используется в качестве стандартного для скриптов, работающих в
pre% section
, Я думаю, это может быть еще один в зависимости от версий RedHat и Fedora. Но действительно легко узнать, какой из них подходит для вашего случая.Каковы
exec {STDOUTBACK}>&1
а такжеexec {STDOUTBACK}>&-
вещи?Иди читать
man bash
и искатьREDIRECTION
раздел, где вы можете найти следующее:
Каждому перенаправлению, которому может предшествовать номер дескриптора файла, вместо этого может предшествовать слово вида {varname}. В этом случае для каждого оператора перенаправления, кроме>&- и <& -, оболочка выделит дескриптор файла больше 10 и присвоит его переменной varname. Если>&- или <& - предшествует {varname}, значение var-name определяет дескриптор файла для закрытия.
Это должен быть комментарий, но...
Вы должны манипулировать stdin,stderr и stdout для вывода whiptail в переменную.
x=`whiptail --inputbox "hello" 10 40 3>&1 1>&2 2>&3`
Это помещает вывод в /tmp/x:
whiptail --inputbox "hello" 10 40 3>/tmp/x 1>&2 2>&3