对我来说,这个问题的起源是,在安装基于 Centos 的自定义发行版时,能够%pre
从 kickstart 文件中的脚本中运行 whiptail 命令。但是,在 Anaconda 中观察到的行为可以通过任何 Linux 系统的虚拟终端轻松重现。
要在 Anaconda 中将 whiptail 命令作为 kickstart%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
,而不是在文本输入、“确定”和“取消”元素之间切换,实际上是在文本输入框中插入一个制表符。同样,使用箭头键会导致在对话框中写入转义序列:
使用 python snack(使用与 whiptail 相同的库 - libnewt)和 dialog 时也会观察到这种行为。
当然,我可以使用交互式 shell 脚本,而不是使用 whiptail,但我只是想知道是否有人对为什么会出现这种行为有任何建议,因为我认为让它工作的唯一要求是正确重定向输入和输出流。
总结
我有兴趣创建一个包含whiptail/dialog命令的脚本,该脚本可以在一个TTY中执行,并且脚本的输出/输入可以发送到/来自不同的TTY。
答案1
这对我有用(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} 形式的单词。在这种情况下,对于除 >&- 和 <&- 之外的每个重定向运算符,shell 将分配一个大于 10 的文件描述符并将其分配给 varname。如果 >&- 或 <&- 前面加有 {varname},则 varname 的值定义要关闭的文件描述符。
答案2
这应该是一条评论,但是......
您必须操作 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