web-dev-qa-db-ja.com

bashスクリプトエラーstty:標準入力:デバイスの不適切なioctl

私はヒアドキュメントをbashスクリプトで使用して、パスワードが何度も要求されるインストールとセットアップを自動化しています。パスワードを1回入力すると、スクリプトはそれをさまざまなコマンドに渡します。ほとんどの場合、ヒアドキュメントのアプローチはこれをうまく処理します。ただし、1つのケースでこのエラーが発生します。

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]/n n

expectを使用する方が良いソリューションでしょうか?もしそうなら、この場合どのように使用しますか? (私はこれまでexpectを使用したことがありませんが、この質問を投稿してから多くの例を見てきました。expectを自分で動作させることはできません。)

16
MountainX

x11vncは、標準入力が端末であることを想定しており、入力時にパスワードがエコーされないように端末モードを変更します。標準入力が端末でない場合、エコーをオフにして再度オンにする stty 呼び出しは失敗するため、警告が表示されます。

期待は確かに解決策です。このスクリプトを試してみてください(テストされていません):

#!/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クライアント証明書)。

これらの警告メッセージを回避する別のオプションは、UNIXコマンドによって作成された疑似ターミナルでx11vncを実行することです( を参照してください)疑似ターミナル(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
5
kalou

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
1
Tim Kennedy