我已经自动化了完成该项目所需的大部分信息,但唯一滞后的是在远程计算机上运行本地 shell 脚本。
我们知道,使用“expect”库的脚本无法识别任何 Linux 命令。
这里我们有两个我尝试过的用例:
仅使用一个 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
在单独的 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
=========================
我相信上述代码就其本身而言应该都是有效的,但是,相同的输出似乎非常出乎意料:
输入密码后,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”的情况下也可以正常工作
这里我们分别执行 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 命令,以便可以正确完成重定向。