【问题标题】:Use of expect to run scripts on remote machine使用期望在远程机器上运行脚本
【发布时间】:2018-08-23 16:06:21
【问题描述】:

我正在做一个需要一些帮助的项目。

我已经自动化了完成这个项目所需的大部分信息,但唯一滞后的是在远程机器上运行本地 shell 脚本。 正如我们所知,使用“expect”库的脚本无法识别任何 Linux 命令。 这里我们有两个我尝试过的用例:

1) 仅使用一个期望脚本在远程服务器上运行所需的命令列表,该脚本既具有脚本执行功能,又具有使用 scp 将输出推送到本地计算机,这是此代码的 sn-p:

`chmod 777 localscript.sh   
cat > script1.sh <<- "ALL"`  
`#!/usr/bin/expect
set password [lindex $argv 0];  
set ipaddress [lindex $argv 1];  
set timevalue [lindex $argv 2];  
set timeout $timevalue  
spawn /usr/bin/ssh username@$ipaddress /bin/bash < ./localscript.sh  
expect "assword:"  
send "$password\r"  
set timeout $timevalue  
spawn /usr/bin/scp username@$2:"/path/from/source/*" /path/to/destination/folder/  
expect "assword:"  
send "$password\r"  
interact  
ALL  
chmod 777 script1.sh  
./script1.sh $password $2 $timevalue`  

2) 在单独的期望脚本中在远程服务器上运行所需的命令列表,并使用 scp 在不同的脚本中获取文件:

`cat > script1.sh <<- "ALL" ` 
`#!/usr/bin/expect
set password [lindex $argv 0];  
set ipaddress [lindex $argv 1];  
set timevalue [lindex $argv 2];  
set timeout $timevalue   
spawn /usr/bin/ssh username@$ipaddress /bin/bash < ./localscript.sh  
expect "assword:"  
send "$password\r"  
interact  
ALL  
cat > script2.sh <<- "ALL2"`  
`#!/usr/bin/expect
set password [lindex $argv 0];  
set ipaddress [lindex $argv 1];  
set timevalue [lindex $argv 2];  
set timeout $timevalue   
spawn /usr/bin/scp username@ipaddress:"/path/from/source/*" /path/to/destination/folder/  
expect "assword:"  
send "$password\r"  
interact  
ALL2  
chmod 777 localscript.sh script1.sh script2.sh   
./script1.sh  $password $2 $timevalue  
sleep 5  
./script2.sh  $password $2 $timevalue`

我相信上述代码在它们自己的方面都应该是有效的,但是,同样的输出似乎是非常出乎意料的:

1) ssh 和 scp 命令在输入密码后几乎同时执行,因此,它没有给 localscript 足够的时间来完成它的工作,这是我看到的输出:

    spawn /usr/bin/ssh username@1.2.3.4 /bin/bash < ./localscript.sh  
    Warning private system unauthorized users will be prosecuted.  
    username@1.2.3.4's password: spawn /usr/bin/scp 
    username@1.2.3.4:"/home/some/file/*" /another/file/  
    Warning private system unauthorized users will be prosecuted.  
    username@1.2.3.4's password:  
    scp: /home/some/file/*: No such file or directory  

请注意:此功能在没有期望的情况下运行良好

2)这里我们分别执行ssh和scp,但是似乎无法识别文件localscript.sh存在:

    spawn /usr/bin/ssh username@1.2.3.4 /bin/bash < ./localscript.sh  
    Warning private system unauthorized users will be prosecuted.  
    username@1.2.3.4's password:  
    bash: localscript.sh: No such file or directory  
    Warning private system unauthorized users will be prosecuted.  
    username@1.2.3.4's password:  
    scp: /home/some/file/*: No such file or directory  

任何对此的反馈都将不胜感激,我认为第一种方法可能是一个可行的解决方案,除了生成速度太快并且“睡眠”或“之后”命令都没有帮助/工作的事实。我认为第二种方法也是有效的,但是在远程服务器上运行本地脚本的方式似乎与我们在 Linux 上使用“expect”时的常用方式不同。

抱歉说了这么多,我希望尽快摆脱痛苦:)

【问题讨论】:

  • 编号项目符号点对于代码 sn-ps 来说很难
  • 看起来你更喜欢 shell 脚本。看看sexpect,你可以用它编写Expect脚本,只用shell代码。

标签: linux shell scripting expect eof


【解决方案1】:

确实,您设置的超时没有像您预期那样工作。两个脚本都生成了,每次生成后的 expect "assword:" 实际上捕获并响应相同的密码提示。

expect 实际上比粗略一瞥会让你相信的更复杂。每个spawn 都应返回一个PID,您可以将其与expect 一起使用以查找特定进程的输出。

expect也可以分解成多个部分,并具有定义子程序的能力。下面是一些更高级的使用示例https://wiki.tcl-lang.org/10045

在这种特定情况下,我建议在生成下一个进程之前等待 scp 完成。

expect {
    "assword:" {
        send "$password\r"
        exp_continue # Keep expecting
    }
    eof {
        puts -nonewline "$expect_out(buffer)"
        # eof so the process should be done
        # It is safe to execute the next spawn
        # without exp_continue this expect will
        # break and continue to the next line
    }
}

【讨论】:

    猜你喜欢
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    • 2011-06-30
    • 2016-04-02
    • 2017-02-28
    • 2012-09-26
    相关资源
    最近更新 更多