1

私は単純な ssh ログイン ラッパー ツールを作成して、非常に多くのサーバーの 1 つに自動ログインできるようにしています。
最初にユーザー入力から説明を取得し、対応する (最も関連性の高い) サーバー IP とパスワードを抽出して、どこかに安全に保存されます。これを使用して、expect スクリプトを作成します。

期待スクリプトは次のようになります。

    spawn ssh2 -q -t Bob@172.23.24.35
    予想 {
        "assword:" {send "Bob123\r"}
    }
    相互作用する

これをexpectにパイプすると(expectはstdinからスクリプトを読み取ることができる)、「interact」に到達するまですべてがうまくいきます。expectは、eofを受け取ってすぐに終了すると主張します。次に、これをtmp.expなどのファイルに保存すると、同じ問題が発生します「expect < tmp.exp」を実行しますが、「expect -f tmp.exp」を実行するとすべて問題ありません。

その理由は、「対話」が fd0 から入力を受け取り、プログラム (またはシェル) によってパイプにリダイレクトされるためだと思います。これは、「expect < xx.exp」のようなことをすると、interact を使用できないということですか? 「interact」コマンドの前に fd0 を実際の端末に再開する方法はありますか? 私はたくさんグーグルで検索しましたが、「close_on_eof 0」のようなものしか得られませんでした。意味も仕組みもわかりません。前もって感謝します!

4

2 に答える 2

3

私はちょうどそれを行う方法を思いつきます。次の例を参照してください。

$ cat foo.exp
if {[catch {
    #  Close stdin and reopen it as /dev/tty. Then we are
    #+ connecting to a tty.
    close stdin
    open /dev/tty
} err]} {
    puts stderr $err
    exit 1
}

# Without this, inputed lines will be echo'ed twice.
set stty_init -echo
spawn bash --noprofile --norc

expect -re {bash-[.0-9]+(#|\$) }
interact

exit
$ expect < foo.exp
spawn bash --noprofile --norc
bash-4.2# ptree $$
705   screen -T dtterm -U
  24164 bash
    26826 expect
      26827 bash --noprofile --norc
        26830 ptree 26827
bash-4.2# exit
exit
$

よりスマートにするためstdinに、最初に が tty かどうかを確認する必要があります。

于 2013-03-13T08:45:27.630 に答える
2

ファイル記述子が tty かどうかを確認する組み込みの方法を提供してTclいるかどうかは不明です。Expect私はこのようにしました:

$ cat foo.exp
if { [catch { system {[[ -t 0 ]]} } error] } {
    puts "stdin is not a tty"
} else {
    puts "stdin is a tty"
}
$ expect foo.exp
stdin is a tty
$ expect < foo.exp
stdin is not a tty
$
于 2013-03-18T03:00:18.337 に答える