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

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

我已经自动化了完成该项目所需的大部分信息,但唯一滞后的是在远程计算机上运行本地 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 [email protected] /bin/bash < ./localscript.sh
    Warning private system unauthorized users will be prosecuted.
    [email protected]'s password: spawn /usr/bin/scp [email protected]:"/home/some/file/*" /another/file/
    Warning private system unauthorized users will be prosecuted.
    [email protected]'s password:
    scp: /home/some/file/*: No such file or directory
    

请注意:此功能在不涉及“expect”的情况下也可以正常工作

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

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

任何关于此问题的反馈都将不胜感激,我认为第一种方法可能是一种可行的解决方案,但 spawn 太快,并且“sleep”或“after”命令都不起作用。我认为第二种方法也有效,但是似乎有一种在远程服务器上运行本地脚本的方法,与我们在 Linux 上使用“expect”时通常使用的方法不同。

答案1

一些注意事项:

  • Expect shebang 行是错误的:# #!/usr/bin/expect应该只是#!/usr/bin/expect
  • 您通过 ssh 进入远程主机,但通过本地计算机进行 scp 操作。这是你的意图吗?
    • spawn如果没有,则应改为第二个send
    • 我怀疑这是 scp“找不到文件”错误的根源。
  • 你用$2而不是$ipaddress
  • 如果你不打算与生成的进程进行实际交互,请等待它结束,而expect eof不是interact
  • 您的 shell 脚本创建“script1.sh”和“script2.sh”,但不创建“localscript.sh”
  • “.sh”不是期望代码的描述性扩展名:“.exp”会更好
  • 引用所有 shell 变量:./script1.sh "$password" "$2" "$timevalue"

我会这样写。显然未经测试:

#!/bin/bash
export password=$1
export ipaddress=$2
export timevalue=${3:--1}    # use default -1 if not specified\

[[ -z "$password" ]]  && { echo "Error: missing password";   exit 1; }
[[ -z "$ipaddress" ]] && { echo "Error: missing IP address"; exit 1; }

/usr/bin/expect -d <<END_EXPECT
    set timeout $env(timevalue)

    spawn sh -c "/usr/bin/ssh username@$env(ipaddress) /bin/bash < ./localscript.sh"
    expect "assword:"
    send "$env(password)\r"
    expect eof

    spawn /usr/bin/scp username@$env(ipaddress):"/path/from/source/*" /path/to/destination/folder/
    expect "assword:"
    send "$env(password)\r"
    expect eof
END_EXPECT

我添加了-d打开预期调试输出的选项。不再需要时将其移除。

问题在于,spawn 命令不知道如何进行 shell 重定向:spawn 正在接收参数“ssh”、“user@host”、“/bin/bash”、“<”(文字小于)、和“./localhost.sh”。我在此处使用 shell 显式执行 ssh 命令,以便可以正确完成重定向。

相关内容