expect是一个自动化交互套件,主要应用于执行命令和程序时,系统以交互形式要求输入指定字符串,实现交互通信。 expect自动交互流程: spawn启动指定进程–>expect获取指定关键字–>send向指定程序发送指定字符–>执行完成退出.
expect命令参数 1 2 3 4 5 6 7 8 9 10 spawn 交互程序开始后面跟命令或者指定程序 expect 获取匹配信息匹配成功则执行expect后面的程序动作 send exp_send 用于发送指定的字符串信息,用于模拟用户输入 exp_continue 在expect中多次匹配就需要用到 send_user 用来打印输出 相当于shell中的echo exit 退出expect脚本 eof expect执行结束 退出 set 定义变量 puts 输出变量 set timeout 设置超时时间
ssh登录远程主机执行命令 1 2 3 4 5 # !/usr/bin/expect spawn ssh root@192.168.59.131 #模拟用户输入ssh root@192.168.59.131以连接主机 expect "password:" #expect从spawn进程接收字符串 send "12345\r" #当上一步的expect接收到指定信息后才会发送12345字符串信息,模拟用户输入密码并\r回车 interact
scp传输文件 expect使用多分支语法时,会进行依次匹配循环,当出现报错时使用exit 1退出循环,eof是在等待结束标志。由spawn启动的命令在结束时会产生一个eof标记,由于scp传输文件过大会导致传输时间过长,所以将timeout 设置为-1即可无限制的等待。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 # !/usr/bin/expect -f set timeout -1 set host [lindex $argv 0] set username [lindex $argv 1] set password [lindex $argv 2] set sshport [lindex $argv 3] set src_file [lindex $argv 4] set dest_file [lindex $argv 5] spawn scp -P $sshport -r $src_file $username@$host:$dest_file expect { "*yes/no*" { send "yes\r" exp_continue } "*assword:*" { send "$password\r" exp_continue } "Permission denied" { send_user "错误:权限被拒绝\n" exit 1 } timeout { send_user "错误:连接超时\n" exit 1 } "100%" { send_user "传输成功\n" } eof }
ftp上传文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 # !/usr/bin/expect -f set timeout -1 set host [lindex $argv 0] set username [lindex $argv 1] set password [lindex $argv 2] set ftpport [lindex $argv 3] set src_file [lindex $argv 4] set dest_dir [lindex $argv 5] spawn sftp -o Port=$ftpport $username@$host expect { "*yes/no*" { send "yes\r" exp_continue } "*assword:*" { send "$password\r" exp_continue } timeout { send_user "错误:连接超时\n" exit 1 } } expect "sftp>" send "cd $dest_dir\r" expect "sftp>" send "put $src_file\r" expect "sftp>" send "bye\r" expect eof
将expect封装到shell函数中 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 function remote_upload_file() { local local_file="$1" local remote_dir="$2" local filename="$3" local host="192.168.59.131" local user="admin" local pass="admin" local port="21" expect -c " set timeout -1 send_user \"开始连接到FTP服务器: $host\n\" spawn ftp $host $port expect { \"Name*\" { send \"$user\r\" exp_continue } \"Password:\" { send \"$pass\r\" } \"Login failed\" { send_user \"FTP登录失败\n\" exit 1 } \"Not connected\" { send_user \"无法连接到FTP服务器\n\" exit 1 } timeout { send_user \"连接超时\n\" exit 1 } } expect { \"ftp>\" { send_user \"成功登录FTP服务器\n\" } \"Login incorrect\" { send_user \"用户名或密码错误\n\" exit 1 } timeout { send_user \"登录响应超时\n\" exit 1 } } send \"cd $remote_dir\r\" expect { \"ftp>\" { send_user \"成功切换到远程目录:$remote_dir\n\" } \"No such file or directory\" { send_user \"远程目录不存在: $remote_dir\n\" send \"bye\r\" expect eof exit 1 } timeout { send_user \"切换目录超时\n\" exit 1 } } send \"binary\r\" expect \"ftp>\" send_user \"开始上传文件: $local_file -> $remote_dir/$filename\n\" send \"put $local_file $filename\r\" expect { \"ftp>\" { send_user \"文件上传成功完成\n\" } \"Transfer complete\" { expect \"ftp>\" send_user \"文件上传成功完成\n\" } \"No such file or directory\" { send_user \"错误: 无法访问本地文件\n\" exit 1 } \"Connection closed\" { send_user \"错误: 连接意外关闭\n\" exit 1 } timeout { send_user \"错误: 上传超时\n\" exit 1 } } send \"bye\r\" expect eof send_user \"FTP会话结束\n\" " function upload_file_ftp() { local file=$(find /data -type f -atime -1 -name "*.gz") #find找到需要上传的文件路径 local filename=$(echo $file|awk -F'/' '{print $NF}') #将获取的文件路径按/切割文件名 local dir="ftp/" echo "$(date +"%Y-%m-%d %H:%M:%S") 开始上传文件: $filename" remote_upload_file "$file" "$dir" "$filename" if [ $? -eq 0 ]; then echo "$(date +"%Y-%m-%d %H:%M:%S") 上传成功" else echo "$(date +"%Y-%m-%d %H:%M:%S") 上传失败" fi }
expect send可能会出现invalid command name或 no such variable 没此变量的报错 将特殊符号进行转义,即[如语句里面特殊符号太多,转义太麻烦。
可以使用send – {}格式,将send的内容放到大括号中转义。
1 2 3 4 5 send "awk 'BEGIN{FS=[ ,]} { print $2+$4 }' file\r " 替换为 send -- {awk 'BEGIN{FS=[ ,]} { print $2+$4 }' file} send -- \r