欢迎各位兄弟 发布技术文章
这里的技术是共享的
这个错误信息通常表示在使用 expect
脚本时,尝试读取一个尚未打开的进程的输出。具体来说,"spawn id exp6 not open" 意味着你尝试与一个未成功启动的子进程进行交互。
可能的原因和解决办法包括:
子进程未成功启动:确保你使用的 spawn
命令正确,并且子进程能够正常启动。例如,检查命令是否正确、路径是否有效。
命令执行失败:如果你在 spawn
后面调用的命令出现错误,expect
将无法与之交互。可以在命令前加上 puts
来输出调试信息,查看具体的错误。
超时设置:如果子进程需要一些时间才能启动,确保你的 expect
脚本有足够的时间等待。可以增加超时时间,例如使用 set timeout 10
。
检查权限:确保你有权限执行该命令,尤其是在需要特权的情况下。
环境问题:有时,环境变量或系统配置问题也会导致子进程无法启动。检查你的环境设置。
如果你能提供更多的代码片段或上下文,我可以帮助你更具体地诊断问题。
这个错误信息 "expect: spawn id exp6 not open while executing 'expect eof'" 通常表示在使用 Expect 脚本时,尝试等待子进程结束(通过 expect eof
)时,指定的 spawn ID(在这个例子中是 exp6
)没有打开。
可能的原因包括:
子进程未成功启动:确保你在 spawn
命令中正确启动了一个子进程。如果子进程没有成功启动,spawn ID 将不会有效。
子进程已经结束:如果子进程在你调用 expect eof
之前就已经结束,Expect 将无法找到该 spawn ID。
错误的 spawn ID:检查你的代码,确保你在使用 expect eof
时使用的是正确的 spawn ID。
确保在调用 expect eof
之前,子进程已成功启动并处于运行状态。
使用 expect
的其他命令(如 expect
或 timeout
)来处理可能的错误情况。
检查脚本中的逻辑,确保 spawn ID 是有效的。
如果你能提供更多的代码或上下文,我可以帮助你更具体地诊断问题。
6. 实例:下面这个脚本是完成对单个服务器scp任务。
1: #!/usr/bin/expect
2:
3: set timeout 10
4: set host [lindex $argv 0]
5: set username [lindex $argv 1]
6: set password [lindex $argv 2]
7: set src_file [lindex $argv 3]
8: set dest_file [lindex $argv 4]
9:
10: spawn scp $src_file $username@$host:$dest_file
11: expect {
12: "(yes/no)?"
13: {
14: send "yes\n"
15: expect "*assword:" { send "$password\n"}
16: }
17: "*assword:"
18: {
19: send "$password\n"
20: }
21: }
22: expect "100%"
23: expect eof
参考源代码图片:
注意代码刚开始的第一行,指定了expect的路径,与shell脚本相同,这一句指定了程序在执行时到哪里去寻找相应的启动程序。代码刚开始还设定了timeout的时间为10秒,如果在执行scp任务时遇到了代码中没有指定的异常,则在等待10秒后该脚本的执行会自动终止。
spawn代表在本地终端执行的语句,在该语句开始执行后,expect开始捕获终端的输出信息,然后做出对应的操作。expect代码中的捕获的(yes/no)内容用于完成第一次访问目标主机时保存密钥的操作。有了这一句,scp的任务减少了中断的情况。代码结尾的expect eof与spawn对应,表示捕获终端输出信息的终止。
有了这段expect的代码,还只能完成对单个远程主机的scp任务。如果需要实现批量scp的任务,则需要再写一个shell脚本来调用这个expect脚本。
1: #!/bin/sh
2:
3: list_file=$1
4: src_file=$2
5: dest_file=$3
6:
7: cat $list_file | while read line
8: do
9: host_ip=`echo $line | awk '{print $1}'`
10: username=`echo $line | awk '{print $2}'`
11: password=`echo $line | awk '{print $3}'`
12: echo "$host_ip"
13: ./expect_scp $host_ip $username $password $src_file $dest_file
15: done
参考代码图片如下:
很简单的代码,指定了3个参数:列表文件的位置、本地源文件路径、远程主机目标文件路径。需要说明的是其中的列表文件指定了远程主机ip、用户名、密码,这些信息需要写成以下的格式:
IP username password
中间用空格或tab键来分隔,多台主机的信息需要写多行内容。
这样就指定了两台远程主机的信息。注意,如果远程主机密码中有“$”、“#”这类特殊字符的话,在编写列表文件时就需要在这些特殊字符前加上转义字符,否则expect在执行时会输入错误的密码。
对于这个shell脚本,保存为batch_scp.sh文件,与刚才保存的expect_scp文件和列表文件(就定义为hosts.list文件吧)放到同一目录下,执行时按照以下方式输入命令就可以了: