Можно ли запустить диалог / сценарий 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

Возможные вопросы:

  1. Почему вы использовали /dev/pts/0?

    Потому что из консоли Anaconda я узнал, какое устройство используется в качестве стандартного для скриптов, работающих в pre% section, Я думаю, это может быть еще один в зависимости от версий RedHat и Fedora. Но действительно легко узнать, какой из них подходит для вашего случая.

  2. Каковы 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
Другие вопросы по тегам