bash 脚本错误 stty:标准输入:设备的 ioctl 不合适

bash 脚本错误 stty:标准输入:设备的 ioctl 不合适

我在 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

相关内容