SSH + Sudo + Bash スクリプトでの Expect: リモート マシンで sudo を使用してコマンドを実行する

SSH + Sudo + Bash スクリプトでの Expect: リモート マシンで sudo を使用してコマンドを実行する

スクリプトを使用して、いくつかの .deb パッケージの展開を自動化しようとしています。SSHsudo dpkg -i $myDeb.debでアクセスできるリモート マシンのリストで実行したいと考えています。

私は、bash スクリプト内で 'expect' を使用してコマンドを自動化しようとしましたが、いくつかの異なるエラーが発生するため、明らかに何かが間違っています (基本的に、引用符をどこに置くかによって異なります)。

これは私が持っている関数です(次のように呼び出されます:_remoteInstallation "myPackage115.deb" "192.168.1.55"。リモートマシンでは、.deb は $HOME/Documents/ にあることがわかっています:

function _remoteInstallation(){
    local retval=1
    local debToInstall=$(basename "$1")
    local remoteMachine="$2"
    spawned=$(expect -d -c "
          set timeout 1800
          spawn "/usr/bin/ssh -t borrajax@$remoteMachine /usr/bin/sudo /usr/bin/dpkg -i /home/borrajax/Documents/$debToInstall"'
          expect {
                \"Are you sure you want to continue connecting\" { send \"yes\r\"; exp_continue }
                \"password\" { send \"myPassword\r\";  exp_continue }
                \"[sudo] password\" { send \"myPassword\r\";  exp_continue }
                default { exit 1 }
          }
    " )
    retval=$?
    return $retval
}

このように引用符が生成された領域では、

expect: invalid option -- 't'

次のように変更すると:

 spawn /usr/bin/ssh -t borrajax@$remoteMachine '/usr/bin/sudo /usr/bin/dpkg -i /home/borrajax/Documents/$debToInstall'

sudo dpkg コマンドをローカルで実行しようとしているようです (最初に '$remoteMachine' に ssh(s) し、次に sudo dpkg をローカルで実行します。これは 2 つの別々のコマンドのようです)

これとともに:

spawn '/usr/bin/ssh -t borrajax@$remoteMachine \'/usr/bin/sudo /usr/bin/dpkg -i /home/borrajax/Documents/$debToInstall\''

それはわかりますcouldn't execute "'/usr/bin/ssh": no such file or directory(それは真実ではありません)

...そしてこの時点で、アイデアが尽きてしまいました...:-)

ヒントがあればありがたいです。ありがとうございます。

答え1

引用符のエスケープのレベルが抜けていると思います。この高度なエスケープでは、引用符が必要となるステージごとに、小さなスクリプトを作成するのが最善です。

それ以外の場合は、この修正バージョンを試すことができます (ただし、このコーディング スタイルは推奨しません)。

function _remoteInstallation(){
    local retval=1
    local debToInstall=$(basename "$1")
    local remoteMachine="$2"
    spawned=$(expect -d -c "
          set timeout 1800
          spawn \"/usr/bin/ssh -t borrajax@$remoteMachine /usr/bin/sudo /usr/bin/dpkg -i /home/borrajax/Documents/$debToInstall\"
          expect {
                \"Are you sure you want to continue connecting\" { send \"yes\r\"; exp_continue }
                \"password\" { send \"myPassword\r\";  exp_continue }
                \"[sudo] password\" { send \"myPassword\r\";  exp_continue }
                default { exit 1 }
          }
    " )
    retval=$?
    return $retval
}

答え2

なぜ人々はいつもこの醜いexpectものを と一緒に使うのでしょうかssh? ssh キーを使用すれば完了です (理論については公開鍵暗号化について読んでください。ssh-copy-id remotemachine練習のために一度だけ使用してください)。その後の使用法は次のように簡単です。

ssh remote-machine "remote-shell-command" > local-redirection-of-command-output

3 つのレベルの引用符を使い分ける必要がなくなると、自然に正しいコマンドを記述できるようになります。

関連情報