我在 bash 脚本中使用here-documents 来自动执行多次需要密码的安装和设置。我输入密码一次,脚本将其传递给各种命令。在大多数情况下,此处文档方法可以很好地处理这个问题。但是,在一种情况下我收到此错误:
Enter VNC password: stty: standard input: Inappropriate ioctl for device
Verify password:
stty: standard input: Inappropriate ioctl for device
请注意,此错误消息来自x11vnc -storepassword
(而不是来自sudo
。)
我的问题与以下相关x11vnc -storepasswd
,这是我的代码:
sudo x11vnc -storepasswd ~/.vnc/passwd << ENDDOC
password
password
y
ENDDOC
显然(从错误来看)这是行不通的。我希望有一个如何sudo x11vnc -storepasswd ~/.vnc/passwd
在脚本中实现的工作示例。
如果有帮助,提示如下所示:
输入VNC密码:
验证密码:
将密码写入/home/user/.vnc/passwd? [y]/nn
使用会expect
是更好的解决方案吗?如果是这样,在这种情况下我将如何使用它? (我以前从未使用过expect
,但自从发布这个问题以来我已经看过很多例子,但我无法expect
自己开始工作。)
答案1
x11vnc
避免这些警告消息的另一个选择是在由 UNIX 命令创建的伪终端中执行(请参阅使用伪终端(pty)控制交互式程序)。这可以通过命令或工具来完成script
,例如pdip
(“使用交互式程序进行编程对话”)。
Mac OS X 10.6.8 上未提供伪终端的警告消息x11vnc
:
# x11vnc 0.9.14
sudo x11vnc -storepasswd ~/.vnc/passwd << ENDDOC
password
password
y
ENDDOC
# Enter VNC password: stty: stdin isn't a terminal
#
# Verify password:
# stty: stdin isn't a terminal
# Write password to ~/.vnc/passwd? [y]/n Password written to: ~/.vnc/passwd
使用命令解决script
:
# GNU script command
sudo script -q -c 'x11vnc -storepasswd ~/.vnc/passwd' <<ENDDOC /dev/null
password
password
y
ENDDOC
# ... or ...
printf '%s\n' 'password' 'password' 'y' |
sudo script -q -c 'x11vnc -storepasswd ~/.vnc/passwd' /dev/null
# FreeBSD script command
sudo script -q /dev/null x11vnc -storepasswd ~/.vnc/passwd <<ENDDOC
password
password
y
ENDDOC
答案2
x11vnc
期望其标准输入是终端,并且它会更改终端模式以避免在您键入时回显密码。当标准输入不是终端时,stty
关闭回声并重新打开的调用失败,因此您会看到警告。
Expect确实是一个解决方案。尝试这个脚本(未经测试):
#!/usr/bin/expect -f
spawn x11vnc -storepasswd ~/.vnc/passwd
expect "password:" {send "swordfish" "\r"}
expect "password:" {send "swordfish" "\r"}
expect "Write*\?" {send "y\r"}
或者,如果可以的话,请使用 RFB 以外的身份验证方法(-passwdfile
或 SSL 客户端证书)。
答案3
Sudo 有一个选项-S
允许它从 STDIN 读取密码。
[user@evil ~]$ tail -1 /etc/shadow
tail: cannot open `/etc/shadow' for reading: Permission denied
[user@evil ~]$ echo 'P@ssW3rd!' | sudo -S tail -1 /etc/shadow
nfsnobody:!!:15891::::::
这是一个演示该过程的示例脚本:
#!/bin/bash
function hr {
perl -e 'print "-" x 80, "\n";'
}
hr
read -p "Please enter your sudo password: " -s sudopasswd
echo
hr
echo "-sudo run: tail -1 /etc/shadow"
tail -1 /etc/shadow
hr
echo "+sudo run: tail -1 /etc/shadow"
echo "$sudopasswd" | sudo -S tail -1 /etc/shadow
hr
echo "-sudo run: ls -la /root/"
ls -la /root/
hr
echo "+sudo run: ls -la /root/"
echo "$sudopasswd" | sudo -S ls -la /root/
hr
您的脚本只需要执行以下操作:
read -p "Please enter your sudo password: " -s sudopasswd
echo "$sudopasswd" | sudo -S x11vnc -storepasswd ~/.vnc/passwd
这将允许您在脚本中使用 sudo 命令,而无需硬编码密码。
或者,您可以添加您的用户或用户子集,使其能够使用 sudo 运行 x11vnc,无需密码,但添加如下行/etc/sudoers
:
user ALL=(root) NOPASSWD: /path/to/x11vnc
或者创建一个vncusers
组,将用户添加到该组,然后将以下内容添加到/etc/sudoers
:
%vncusers ALL=(root) NOPASSWD: /path/to/x11vnc