linux - 使用 expect 在远程机器上运行脚本

标签 linux shell scripting expect eof

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

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

1) 仅使用一个 expect 脚本在远程服务器上运行所需的命令列表,该脚本具有脚本执行以及使用 scp 将输出推送到本地机器,这里是这段代码的片段:

`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) 在单独的 expect 脚本中在远程服务器上运行所需的命令列表,并使用 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  

请注意:此功能在没有 expect 参与的情况下工作正常

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  

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

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

最佳答案

实际上,您设置的超时没有像您期望的那样工作。两个脚本都生成了,每次生成后的 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
    }
}

关于linux - 使用 expect 在远程机器上运行脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51990021/

相关文章:

bash - 如何将变量重定向到文件但不显示在屏幕上

sql - 有没有办法将 BigQuery 交互式 shell 结果保存到文件中?

scripting - Shell 脚本搜索和删除非文本文件

mysql - Powershell InvalidOperation错误

python - 如何使用 Python 解析由自定义协议(protocol)数据包组成的 TCP 流

Linux,shell脚本] 如何通过文件夹名搜索动态删除文件夹

windows - 批处理 - 检查变量是否不为空并执行操作

linux - netcat 连接成功后显示欢迎信息

检查文件是否存在,包括在 PATH 中

linux - 在我的代码末尾进行系统调用后出现程序集段错误