【转】使用expect实现shell自动交互
2015-10-28 18:41
441 查看
原文地址:http://www.nginx.cn/1934.html
shell脚本需要交互的地方可以使用here文档是实现,但是有些命令却需要用户手动去就交互如passwd、scp
对自动部署免去用户交互很痛苦,expect能很好的解决这类问题。
expect的核心是spawn expect send set
spawn 调用要执行的命令
expect 等待命令提示信息的出现,也就是捕捉用户输入的提示:
send 发送需要交互的值,替代了用户手动输入内容
set 设置变量值
interact 执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。
expect eof 这个一定要加,与spawn对应表示捕获终端输出信息终止,类似于if....endif
expect脚本必须以interact或expect eof结束,执行自动化任务通常expect eof就够了。
设置expect永不超时
set timeout -1
设置expect 300秒超时,如果超过300没有expect内容出现,则推出
set timeout 300
expect编写语法,expect使用的是tcl语法。
一条Tcl命令由空格分割的单词组成. 其中, 第一个单词是命令名称, 其余的是命令参数
cmd arg arg arg
$符号代表变量的值. 在本例中, 变量名称是foo.
$foo
方括号执行了一个嵌套命令. 例如, 如果你想传递一个命令的结果作为另外一个命令的参数, 那么你使用这个符号
[cmd arg]
双引号把词组标记为命令的一个参数. "$"符号和方括号在双引号内仍被解释
"some stuff"
大括号也把词组标记为命令的一个参数. 但是, 其他符号在大括号内不被解释
{some stuff}
反斜线符号是用来引用特殊符号. 例如:n 代表换行. 反斜线符号也被用来关闭"$"符号, 引号,方括号和大括号的特殊含义
expect使用实例
1。首先确认expect的包要安置。
#rpm -qa | grep expect
如果没有则需要下载安装,
#yum install expect
2.安装完成后,查看expect的路径,可以用
#which expect
/usr/bin/expect
3.编辑脚本
#vi autosu.sh
添加如下内容
4.确定脚本有可执行权限
chmod +x autosu.sh
5.执行脚本 expect autosu.sh 或 ./autosu.sh
expect常用脚本
登陆到远程服务器
scp拷贝文件
使用方法
./expect_scp 192.168.75.130 root 123456 /root/src_file /root/dest_file
以上的命令执行后,将把本地/root目录下的src_file文件拷贝到用户名为root,密码为123456的主机192.168.75.130中的/root下,同时还将这个源文件重命名为dest_file
一样例:
#!/bin/bash
src_host=$1
src_username=$2
src_passwd=$3
dst_host=$4
dst_username=$5
dst_passwd=$6
#在远程主机1上生成公私钥对
Keygen()
{
expect << EOF
spawn ssh $src_username@$src_host ssh-keygen -t rsa
while 1 {
expect {
"password:" {
send "$src_passwd\n"
}
"yes/no*" {
send "yes\n"
}
"Enter file in which to save the key*" {
send "\n"
}
"Enter passphrase*" {
send "\n"
}
"Enter same passphrase again:" {
send "\n"
}
"Overwrite (y/n)" {
send "n\n"
}
eof {
exit
}
}
}
EOF
}
#从远程主机1获取公钥保存到本地
Get_pub()
{
expect << EOF
spawn scp $src_username@$src_host:~/.ssh/id_rsa.pub /tmp
expect {
"password:" {
send "$src_passwd\n";exp_continue
}
"yes/no*" {
send "yes\n";exp_continue
}
eof {
exit
}
}
EOF
}
#将公钥的内容附加到远程主机2的authorized_keys
Put_pub()
{
src_pub="$(cat /tmp/id_rsa.pub)"
expect << EOF
spawn ssh $dst_username@$dst_host "chmod 700 ~/.ssh;echo $src_pub >> ~/.ssh/authorized_keys;chmod 600 ~/.ssh/authorized_ke
ys"
expect {
"password:" {
send "$dst_passwd\n";exp_continue
}
"yes/no*" {
send "yes\n";exp_continue
}
eof {
exit
}
}
EOF
}
Keygen
Get_pub
Put_pub
复制代码
脚本主要由3个expect组成,比较简单,用法是
./ssh_trust.sh host1 user1 passwd1 host2 user2 passwd2
复制代码
即建立从user1@host1到user2@host2的ssh信任。
说明:
1、当然得安装expect
2、脚本放在第三方机器(能远程登录host1和host2)上运行即可,当然放在host1和host2上运行也行。
3、如果想批量建立信任,可以编辑一个文件夹file如:
host1 user1 passwd1 host2 user2 passwd2
host3 user3 passwd3 host4 user4 passwd4
host5 user5 passwd5 host6 user6 passwd6
复制代码
使用下面命令执行脚本即可:
xargs -n6 ./ssh_trust.sh < file
复制代码
4、仓促写的,脚本只是简单实现功能,使用前确保参数的可用性(用户密码主机名),不然很容易报错
5、只在linux redhat上测试过,运行成功,欢迎大家提意见~~
shell脚本需要交互的地方可以使用here文档是实现,但是有些命令却需要用户手动去就交互如passwd、scp
对自动部署免去用户交互很痛苦,expect能很好的解决这类问题。
expect的核心是spawn expect send set
spawn 调用要执行的命令
expect 等待命令提示信息的出现,也就是捕捉用户输入的提示:
send 发送需要交互的值,替代了用户手动输入内容
set 设置变量值
interact 执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。
expect eof 这个一定要加,与spawn对应表示捕获终端输出信息终止,类似于if....endif
expect脚本必须以interact或expect eof结束,执行自动化任务通常expect eof就够了。
设置expect永不超时
set timeout -1
设置expect 300秒超时,如果超过300没有expect内容出现,则推出
set timeout 300
expect编写语法,expect使用的是tcl语法。
一条Tcl命令由空格分割的单词组成. 其中, 第一个单词是命令名称, 其余的是命令参数
cmd arg arg arg
$符号代表变量的值. 在本例中, 变量名称是foo.
$foo
方括号执行了一个嵌套命令. 例如, 如果你想传递一个命令的结果作为另外一个命令的参数, 那么你使用这个符号
[cmd arg]
双引号把词组标记为命令的一个参数. "$"符号和方括号在双引号内仍被解释
"some stuff"
大括号也把词组标记为命令的一个参数. 但是, 其他符号在大括号内不被解释
{some stuff}
反斜线符号是用来引用特殊符号. 例如:n 代表换行. 反斜线符号也被用来关闭"$"符号, 引号,方括号和大括号的特殊含义
expect使用实例
1。首先确认expect的包要安置。
#rpm -qa | grep expect
如果没有则需要下载安装,
#yum install expect
2.安装完成后,查看expect的路径,可以用
#which expect
/usr/bin/expect
3.编辑脚本
#vi autosu.sh
添加如下内容
#!/usr/bin/expect -f //这个expect的路径就是用which expect 查看的结果 spawn su - nginx //切换用户 expect "password:" //提示让输入密码 send "testr" //输入nginx的密码 interact //操作完成
4.确定脚本有可执行权限
chmod +x autosu.sh
5.执行脚本 expect autosu.sh 或 ./autosu.sh
expect常用脚本
登陆到远程服务器
#!/usr/bin/expect set timeout 5 set server [lindex $argv 0] set user [lindex $argv 1] set passwd [lindex $argv 2] spawn ssh -l $user $server expect { "(yes/no)" { send "yesr"; exp_continue } "password:" { send "$passwdr" } } expect "*Last login*" interact
scp拷贝文件
#!/usr/bin/expect set timeout 10 set host [lindex $argv 0] //第1个参数,其它2,3,4参数类似 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 "yesn" expect "*assword:" { send "$passwordn"} } "*assword:" { send "$passwordn" } } expect "100%" expect eof
使用方法
./expect_scp 192.168.75.130 root 123456 /root/src_file /root/dest_file
以上的命令执行后,将把本地/root目录下的src_file文件拷贝到用户名为root,密码为123456的主机192.168.75.130中的/root下,同时还将这个源文件重命名为dest_file
一样例:
自动建立ssh信任脚本
在工作中经常遇到给两台主机建立ssh信任,手动建立太费事了,索性胡乱写了个脚本ssh_trust.sh来自动建立信任:#!/bin/bash
src_host=$1
src_username=$2
src_passwd=$3
dst_host=$4
dst_username=$5
dst_passwd=$6
#在远程主机1上生成公私钥对
Keygen()
{
expect << EOF
spawn ssh $src_username@$src_host ssh-keygen -t rsa
while 1 {
expect {
"password:" {
send "$src_passwd\n"
}
"yes/no*" {
send "yes\n"
}
"Enter file in which to save the key*" {
send "\n"
}
"Enter passphrase*" {
send "\n"
}
"Enter same passphrase again:" {
send "\n"
}
"Overwrite (y/n)" {
send "n\n"
}
eof {
exit
}
}
}
EOF
}
#从远程主机1获取公钥保存到本地
Get_pub()
{
expect << EOF
spawn scp $src_username@$src_host:~/.ssh/id_rsa.pub /tmp
expect {
"password:" {
send "$src_passwd\n";exp_continue
}
"yes/no*" {
send "yes\n";exp_continue
}
eof {
exit
}
}
EOF
}
#将公钥的内容附加到远程主机2的authorized_keys
Put_pub()
{
src_pub="$(cat /tmp/id_rsa.pub)"
expect << EOF
spawn ssh $dst_username@$dst_host "chmod 700 ~/.ssh;echo $src_pub >> ~/.ssh/authorized_keys;chmod 600 ~/.ssh/authorized_ke
ys"
expect {
"password:" {
send "$dst_passwd\n";exp_continue
}
"yes/no*" {
send "yes\n";exp_continue
}
eof {
exit
}
}
EOF
}
Keygen
Get_pub
Put_pub
复制代码
脚本主要由3个expect组成,比较简单,用法是
./ssh_trust.sh host1 user1 passwd1 host2 user2 passwd2
复制代码
即建立从user1@host1到user2@host2的ssh信任。
说明:
1、当然得安装expect
2、脚本放在第三方机器(能远程登录host1和host2)上运行即可,当然放在host1和host2上运行也行。
3、如果想批量建立信任,可以编辑一个文件夹file如:
host1 user1 passwd1 host2 user2 passwd2
host3 user3 passwd3 host4 user4 passwd4
host5 user5 passwd5 host6 user6 passwd6
复制代码
使用下面命令执行脚本即可:
xargs -n6 ./ssh_trust.sh < file
复制代码
4、仓促写的,脚本只是简单实现功能,使用前确保参数的可用性(用户密码主机名),不然很容易报错
5、只在linux redhat上测试过,运行成功,欢迎大家提意见~~
相关文章推荐
- SHEll 学习内容
- ShellExecute调用程序出现R6010 -abort() has been called
- shell 简单例子(五)
- mongo shell启动配置文件.mongorc.js(四)
- mongo shell启动配置文件.mongorc.js(三)
- mongo shell启动配置文件.mongorc.js(二)
- mongo shell启动配置文件.mongorc.js(二)
- linnux shell 数组
- mongo shell启动配置文件.mongorc.js(一)
- 一行统计shell
- 无法创建名为“WScript.Shell”的对象
- 《Linux Shell》笔记之grep与正则表达式(实例总结) 未完待续
- Shell date
- shell 脚本完成对日志文件的提取之awk 学习
- linux下修改环境变量文件.bashrc
- vxWorks shell命令
- bash: ./device/nexell/tools/build.sh: 权限不够
- eclipse4 以后,RCP 界面开发configurer.setShellStyle(SWT.MIN | SWT.CLOSE);不生效的解决方法
- mysql linux备份shell
- 如何用PowerShell查看Application Pool Name对应的Service或者Web Application?