expect 中文手册:http://xstarcd.github.io/wiki/shell/expect_handbook.html
TCL 手册:https://www.yiibai.com/tcl/tcl_environment.html
执行
命令行中执行expect 脚本
expect可以让你使用“-c”选项,直接在命令行中执行它,如下所示:
$ expect -c ‘expect “\n” {send “pressed enter\n”}
pressed enter
$
如果你执行了上面的脚本,它会等待输入换行符(\n)。按“enter”键以后,它会打印出“pressed enter”这个消息,然后退出。
交互式执行 expect 脚本
使用“-i”选项,可以通过来自于标准输入的读命令来交互地执行expect脚本。如下所示:
$ expect -i arg1 arg2 arg3
expect1.1>set argv
arg1 arg2 arg3
expect1.2>
逐行执行
通常,expect会在执行脚本之前,把整个脚本都读入到内存中。“-b”选项可以让expect一次只读取脚本中的一行。当你没有写完整个脚本的时候,这是十分有用的,expect可以开始执行这个不完整的脚本,并且,它可以避免把脚本写入到临时文件中。
$ expect -b
示例
ssh 登录输入密码
登录 ssh 并获取输入权
#file: jump.sh#!/usr/bin/expectset timeout 30spawn ssh -p 2222 xxxx@xxx.xxx.xx.comexpect "*password:"send "password\r"interact
interact 是将tty 控制权交给用户
bash 里包裹 expect 代码
#!/bin/bashpasswd='123456'/usr/bin/expect <<-EOFset time 30spawn ssh saneri@192.168.56.103 df -Thexpect {"*yes/no" { send "yes\r"; exp_continue }"*password:" { send "$passwd\r" }}expect eofEOF
使用命令行中的参数
#!/usr/bin/expectset dir [lindex $argv 0]set name lixiaoguangset pwd WKCYmB1PIVZaUiscd /home/bae/wwwroot/$dirspawn git pull --rebaseexpect "*Username*"send "$name\n"expect "*Password*"send "$pwd\n"interact
示例四
#!/usr/bin/expect
set user [lindex $argv 0] //第一个参数
set host [lindex $argv 1] //第二个参数
set passwd "123123a"
set cm [lindex $argv 2] //第三参数
spawn ssh $user@$host
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
expect "]*"
send "exit\r"
更多示例
https://www.cnblogs.com/saneri/p/10819348.html
登录远程服务器后继续执行其他命令
方式1 后续执行的命令放入的 “” 中
- 双引号中写你需要在目标服务器上执行的脚本,
- 支持换行,不用加\
- 两个命令之间需要使用分号‘;’隔开。
如果脚本内容过于复杂,你可以在目标服务器上写好一个可执行的脚本文件 example.sh ,然后讲双引号中的内容改成”./example.sh”来执行,有了这个功能基本就能实现所有的需求了。
spawn ssh admin@xxxxxx.com "
ls;
pwd;
tail -n sdfsdfsdf.log
"
expect "password"
send "xxxxx\r"
expect eof
方式2:bash expect 穿插执行
#!/bin/bash
read -s PWD
/usr/bin/expect <<EOD
spawn ssh admin@koubei.inc.alipay.net "
ls;
tail kb-webroot/server/Resources/Cookies/stable_Cookie.cookie"
expect "password"
send "$PWD\n"
expect eof
EOD
ls
echo "call me crazy"
若果你需要先在本地环境执行脚本拿到一些参数,然后传递给目标服务器,最后在目标服务器获得结果之后回到本地shell,这时候就需要穿插使用。
关键字
spawn 交互程序开始后面跟命令或者指定程序
expect 获取匹配信息匹配成功则执行expect后面的程序动作
expect eof 这个一定要加,与spawn对应表示捕获终端输出信息终止,类似于if….endif
send exp_send 用于发送指定的字符串信息
exp_continue 在expect中多次匹配就需要用到
send_user 用来打印输出 相当于shell中的echo
exit 退出expect脚本
eof expect执行结束 退出
set 定义变量
puts 输出变量
set timeout 设置超时时间
变量
定义变量
#!/usr/bin/expect
#设置expect 命令等待的超时时间,单位秒
set timeout 30
set name ll
获取脚本变量
#!/usr/bin/expect
#设置expect 命令等待的超时时间,单位秒
set timeout [lindex $argv 0] #第一个脚本参数
set name [lindex $argv 1] #第二个脚本参数
处理变量
#!/usr/bin/expect
#设置expect 命令等待的超时时间,单位秒
set timeout [lindex $argv 0]
set timeout2 [exec dc -e $timeout] #处理变量
输入变量
#!/usr/bin/expect
set timeout 30
puts "$timeout"
交互
执行命令,并进行匹配
#!/usr/bin/expect
...
spawn ssh -l username 192.168.1.1
匹配期待输出
#!/usr/bin/expect
...
expect "password:"
#这个命令的意思是判断上次输出结果里是否包含“password:”的字符串,如果有则立即返回,否则就等待一段时间后返回,这里等待时长就是前面设置的30秒
输入内容
#!/usr/bin/expect
...
send "ispass\r"
复合写法
spawn ssh root@$ip //发送ssh请滶
expect { //返回信息匹配
"*yes/no" { send "yes\r"; exp_continue} //第一次ssh连接会提示yes/no,继续
"*password:" { send "$password\r" } //出现密码提示,发送密码
}
#继续执行其他命令
expect "#*"
send "pwd\r"
send "exit\r"
expect eof
嵌套写法
#!/usr/bin/expect
set timeout 10
set host [lindex $argv 0]
set username [lindex $argv 1]
set password [lindex $argv 2]
set src_file [lindex $argv 3]
set dest_file [lindex $argv 4]
spawn scp $src_file $username@$host:$dest_file
expect {
"(yes/no)?"
{
send "yes\n"
expect "*assword:" { send "$password\n"}
}
"*assword:"
{
send "$password\n"
}
}
expect "100%"
expect eof
结束方式
保持交互状态
#!/usr/bin/expect
...
interact
退出
#!/usr/bin/expect
...
expect eof
相互调用
bash 里调用 expect
vim send_key.sh
#!/bin/bash
ssh-keygen -t dsa
for (( i = 1; i <= 100 ; i ++ ))
do
./scp_key_to_node.exp $i
done
vim scp_key_to_node.exp
#!/usr/bin/expect
set timeout 5
set hostno [lindex $argv 0]
spawn scp ~/.ssh/id_dsa.pub impala$hostno:~/.ssh/pub_key
expect "*password*"
send "111111\r"
spawn ssh impala$hostno "cat ~/.ssh/pub_key/ >> ~/.ssh/authorized_keys"
expect "*password*"
send "111111\r"
spawn ssh impala$hostno "chmod 600 ~/.ssh/authorized_keys"
expect "*password*"
send "111111\r"
expect eof
#!/bin/bash
USER=mynameuser
PASS=oldpassword
NPASS=newpassword
expect << EOF
spawn passwd
expect "Changing password for ${USER}."
send "${PASS}\r"
expect "Enter new UNIX password:"
send "${NPASS}\r"
expect "Retype new UNIX password:"
send "${NPASS}\r"
expect eof;
EOF
