Bash 脚本中的 SSH + Sudo + Expect:在远程计算机中使用 sudo 运行命令

Bash 脚本中的 SSH + Sudo + Expect:在远程计算机中使用 sudo 运行命令

我正在尝试使用脚本自动部署一些 .deb 包。我想在sudo dpkg -i $myDeb.deb可以通过 ssh 访问的远程计算机列表中执行。

我尝试在 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 命令(首先 ssh 到“$remoteMachine”,然后在本地运行 sudo dpkg,就像两个单独的命令)

有了这个:

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 个级别的引用之间切换,您自然会编写正确的命令。

相关内容