我正在尝试使用脚本自动部署一些 .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 个级别的引用之间切换,您自然会编写正确的命令。