expect-自动输入密码-交互-shell
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
expect-⾃动输⼊密码-交互-shell
...
⽅法⼀:
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 "test\r"//输⼊nginx的密码
interact //操作完成
4.确定脚本有可执⾏权限
chmod +x autosu.sh
5.执⾏脚本 expect autosu.sh 或 ./autosu.sh
expect常⽤脚本
登陆到远程服务器
#!/usr/bin/expect set timeout 5set server [lindex $argv 0]set user [lindex $argv 1]set passwd [lindex $argv 2]
spawn ssh -l $user $server
expect {"(yes/no)"{ send "yes\r"; exp_continue }"password:"{ send "$passwd\r"}}
expect "*Last login*" interact
scp拷贝⽂件
#!/usr/bin/expectset timeout 10set 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 "yes\n"
expect "*assword:"{ send "$password\n"}}"*assword:"{
send "$password\n"}}
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
======================================================
⼀、简便切换⽤户:
切换⽤户,每次输⼊密码,⽐较⿇烦,可以使⽤脚本交互式登录实现,每次只要输⼊./su_ 并tab,执⾏此脚本,即可切换⾄root⽤户,⽐较简单。
如下:
hao@hao-ubuntu:~$ cat su_root.sh
#!/usr/bin/expect
set timeout 3
spawn su
expect "Password:"
exec sleep 1
send "root\r"
expect "#"
interact
hao@hao-ubuntu:~$ ./su_root.sh
spawn su
Password:
root@hao-ubuntu:/home/hao#
当然也可以增加⼀些if判断之类,让其他⽤户切换也不必输⼊密码。
具体根据个⼈喜欢⾃⼰修改完善。
⼆、交互式登录:
通过expect,实现交互式登录,且看如下脚本:
hao@hao-ubuntu:~$ cat login.sh
#!/usr/bin/expect -f
set ipaddr "192.168.77.58"
set passwd "hao"
spawn ssh hao@$ipaddr
#spawn 意思是执⾏命令,expect内命令,shell中不存在
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
#expect "]# "
#echo '----------------login $ipaddr SUCC!--------------'
#send "touch a.txt\r"
#意思为发送命令
#send "exit\r"
expect eof
exit
===========================================
另外尝试修改sh,或者alias,使其随处可以调⽤,⽽不是只能到固定位置执⾏脚本才可以,或许更为优化。
当然此脚本稍微可以带来便利,但是也存在安全风险。
补充⼀点内容:
对如上内容可以详细解释如下:expect spawn、linux expect ⽤法
使⽤expect实现⾃动登录的脚本,⽹上有很多,可是都没有⼀个明⽩的说明,初学者⼀般都是照抄、收藏。
可是为什么要这么写却不知其然。
本⽂⽤⼀个最短的例⼦说明脚本的原理。
脚本代码如下:
##############################################
#!/usr/bin/expect
set timeout 30
spawn ssh -l username 192.168.1.1
expect "password:"
send "ispass\r"
interact
##############################################
1. [#!/usr/bin/expect]
这⼀⾏告诉操作系统脚本⾥的代码使⽤那⼀个shell来执⾏。
这⾥的expect其实和linux下的bash、windows下的cmd是⼀类东西。
注意:这⼀⾏需要在脚本的第⼀⾏。
2. [set timeout 30]
基本上认识英⽂的都知道这是设置超时时间的,现在你只要记住他的计时单位是:秒
3. [spawn ssh -l username 192.168.1.1]
spawn是进⼊expect环境后才可以执⾏的expect内部命令,如果没有装expect或者直接在默认的SHELL下执⾏是找不到spawn命令的。
所以不要⽤ “which spawn“之类的命令去找spawn命令。
好⽐windows⾥的dir就是⼀个内部命令,这个命令由shell⾃带,你⽆法找到⼀个 或 dir.exe 的可执⾏⽂件。
它主要的功能是给ssh运⾏进程加个壳,⽤来传递交互指令。
4. [expect "password:"]
这⾥的expect也是expect的⼀个内部命令,有点晕吧,expect的shell命令和内部命令是⼀样的,但不是⼀个功能,习惯就好了。
这个命令的意思是判断上次输出结果⾥是否包含“password:”的字符串,如果有则⽴即返回,否则就等待⼀段时间后返回,这⾥等待时长就是前⾯设置的30秒
5. [send "ispass\r"]
这⾥就是执⾏交互动作,与⼿⼯输⼊密码的动作等效。
温馨提⽰:命令字符串结尾别忘记加上“\r”,如果出现异常等待的状态可以核查⼀下。
6. [interact]
执⾏完成后保持交互状态,把控制权交给控制台,这个时候就可以⼿⼯操作了。
如果没有这⼀句登录完成后会退出,⽽不是留在远程终端上。
如果你只是登录过去执⾏
#!/usr/bin/expect #注意安装的路径,不确定 whereis expect ⼀下
# Change a login shell to bash
set user [lindex $argv 0]
spawn bash $user
expect "]:"
send "/bin/bash "
expect eof
exit
3. ⾃动ssh/scp脚本
如果需要从A,到B,然后才能够到C,那么需要ssh和scp两次,是⽐较⿇烦的。
ssh⾃动登录:
#!/usr/bin/expect -f
set timeout 30
spawn ssh weiqiong@B
expect "password:"
send "ppppppr"
expect "]*"
send "ssh weiqiong@Cr"
expect "password:"
send "ppppppr"
interact
scp从A拷贝⽂件到C:
#!/usr/bin/expect -f
set timeout 300
set file [lindex $argv 0]
spawn scp $file weiqiong@B:/home/weiqiong
expect "password:"
send "ppppppr"
expect "]*"
spawn ssh weiqiong@B
expect "password:"
send "ppppppr"
expect "]*"
send "scp $file weiqiong@C:/home/weiqiongr"
expect "password:"
send "ppppppr"
expect "]*"
exit
interact
scp从C拷贝⽂件到A:
#!/usr/bin/expect -f
set timeout 300
set file [lindex $argv 0]
spawn ssh weiqiong@B
expect "password:"
send "ppppppr"
expect "]*"
send "scp weiqiong@C:/home/weiqiong/$file .r"
expect "password:"
send "ppppppr"
expect "]*"
send "exitr"
expect "]*"
spawn scp weiqiong@B:/home/weiqiong/$file .
expect "password:"
send "ppppppr"
interact
4. 建⽴ssh/scp通道
⽐如说我的机器是A,中间服务器为B,⽬标服务器是C
从A可以ssh到B,从B可以ssh到C,但是A不能直接ssh到C
现在展⽰利⽤ssh通道技术从A直接传输⽂件到C
1. ssh -L1234:C:22 userid@B
input B's password
(1234是本机A的空闲端⼝,该指令需要A机器上的root⽤户权限,实际上是在本机1234端⼝建⽴了⼀个通道)
2. 打开⼀个新的console,键⼊:
scp -P1234 filename userid@localhost:
input C's password
下⾯给出scp和ssh的使⽤⽰例:
1、scp
1. expect -c "
2. spawn scp root@1.2.
3.4:/root/1.log /root
3. expect {
4. \"*assword\" {set timeout 300; send \"password\r\";}
5. \"yes/no\" {send \"yes\r\"; exp_continue;}
6. }
7. expect eof"
2、ssh
1. #!/bin/bash
2. expect -c "
3. spawn ssh root@192.168.1.204 \"ls;\"
4. expect {
5. \"*assword\" {set timeout 300; send \"password\r\";}
6. \"yes/no\" {send \"yes\r\"; exp_continue;}
7. }
8. expect eof
9. "
#!/usr/bin/expect
spawn /usr/bin/ssh
expect "*password:"
send "123456\r"
expect "*]#"
send "cd /root"
expect "*]#"
send "exit\r"
expect eof
能看懂吧。
我就是连进去后执⾏了⼀个cd命令。
你可以把你的shell单独写⼀个脚本,在这⾥嵌套⼀下就⾏
================================================
今天b问我如何实现在shell中使⽤su切换⾃动输⼊密码的问题,Google了⼀下,发现了expect这个好东西,写了个简单的demo:
#!/usr/bin/expect
set timeout 30
spawn su -
expect “Password:”
send “rootroot\r”
interact
从shell的写法上就很明显的看到,expect也是类似⼀个shell环境。
基本写法就是spawn后跟需要⾃动匹配输⼊的命令,然后expect后跟匹配的⽂本,send发送需要⼿动输⼊的⽂本。
interact表⽰切换⾄root之后保持交互,如果没有则仍会退⾄原⽤户的shell。
⽅法⼆:
就是expect,perl,python都是⽤的这个模块,读⼊密码,然后⾃动发送过去
对于这两个问题,有⼀个⽐较简单的解决⽅案,那就是管道。
管道其实是⼀种重定向技术,Linux所提供的管道符“|”将两个命令隔开,管道符左边命令的输出就会作为管道符右边命令的输⼊。
连续使⽤管道意味着第⼀个命令的输出会作为第⼆个命令的输⼊,第⼆个命令的输出⼜会作为第三个命令的输⼊,依此类推。
现在,我们先来看看如何使⽤管道来为我们⾃动输⼊密码:
echo 123456 | sudo -S command
这⾥有两条指令,前⾯⼀条是输出123456(假设这就是你的密码),⽽后⾯的指令就是取得管理员权限,它会提⽰你输⼊密码。
这⾥由于采⽤管道提⽰符,⾃动的将前⾯的密码输⼊给第⼆条指令,所以现在你就⾃动完成了密码的输⼊任务啦。
⽤这种⽅式虽然密码是明⽂存在脚本中,不太安全,但是胜在⽅法简单。
然后,对第⼆种情况,同样采⽤管道命令:
echo ‘show database’ | mysql -u root -p ***
这⾥就⾃动的将show database输⼊到进⼊SQL后的新的命令提⽰符后⾯,这条命令现在是可以⾃动执⾏了的。
在编写shell脚本的批处理代码时,⼀般只要求⽤户在调⽤shell时,输⼊有限的⼏个参数,然后由shell进⾏批处理作业,在批处理作业完成之前,中途不会有任何打断。
但是linux有些命令本⾝是要求进⾏⼈机交互的,命令基本上是以⼀问⼀答形式在终端上跟⽤户交互,如passwd、smbpasswd,在设置某个⽤户的密码时,传⼊username参数,回车后系统要求输⼊密码,⽽smbpasswd还要求再次输⼊确认密码,这样就需要⼈⼯⼲预2次,这个命令才能执⾏完毕。
有没有什么办法不⽤⽤户⼲预,由系统模拟⽤户完成输⼊操作呢?答案是肯定的,就是利⽤linux的管道技术,通过“echo”命令进⾏标准输出,然后通过管道符“|”转换为passwd和smbpasswd的标准输⼊,由此模拟⼈机交互,具体实现:
#通过设定--stdin参数,指明接受标准输⼊;
echo $password | passwd - -stdin $userName;。