web-dev-qa-db-ja.com

expectを使用して、スペースを含む引数を指定してコマンドを生成します

expectを使用して、ssh経由で単純なコマンドcat /tmp/id_rsa.pubを実行したいと思います。

シェルでは、この2つの問題を実行できます(手動でパスワードを入力します)

ssh root@localhost 'cat /tmp/id_rsa.pub'

これをexpectで自動化したい。私のexpectスクリプトは、

#!/usr/bin/expect
eval spawn ssh root@localhost 'cat /tmp/id_rsa.pub'
expect "password:"
send "123456"
expect eof

エラーbash: cat /tmp/id_rsa.pub: no such file or directoryをスローします。それは私には非常に奇妙に見えます。考えられる原因は何ですか?

編集:いくつかのテストの後、これはcatの場合だけでなく、一般的であることがわかりました。生成されたコマンドの引数にスペースが含まれている場合(引用符で囲まれている場合でも)、問題が発生します。たとえば、cat /tmp/id_rsa.pubを他のコマンドでスペースに置き換えます。

eval spawn ssh root@localhost 'which Java'

bash: which Java: command not foundで文句を言う。しかし、それをpwdに置き換えると、

eval spawn ssh root@localhost 'pwd'

それはうまくいきます。

10
Richard

単一引用符(')は、shや他の互換シェルとは異なり、Expectに特別な意味はありません。
これはあなたのステートメントが

spawn ssh root@localhost 'cat /tmp/id_rsa.pub'

次の単語に解析されます。

  • spawn
  • ssh
  • root@localhost
  • 'cat-他の一重引用符まで。
  • /tmp/id_rsa.pub'

Shでの使用法は、これを単一の引数にグループ化することです。 Tclでは、二重引用符(")または中括弧({})のいずれかを使用できます。二重引用符で囲むと、Tcl変数が置換され、{}内のコンテンツは置換せずに渡されます。1

tl; dr shの'に相当するExpect/Tclは{}です。

1 改行の前の\は引き続き置換されます。

4
Johannes Kuhn

ヨハネスが言ったように、'が機能しません。
同様の問題が発生しましたが、さらにコマンドを実行して、ログインシェルを取得したかったのです。 "

expect -c "
   set timeout 5;
   spawn ssh -XY $user@$Host -t \"cat /etc/motd; bash -l\"
   expect {
      -re \"^Warning.*\" {exp_continue}
      -re \"^.*sword: \" {send \"${PASSWORDS[$user]}\r\"; interact}
   }
"
4
genesys87

そこにはevalは必要ないと思います。取り外して確認してください。

expectの使用方法」の詳細な例については、これを確認してください 例のリンクを期待してください

お役に立てれば。

0
mtk