expect TCL编程解决shell交互问题

简介:

使用expect实现自动登录的脚本,解决ssh登录认证密码输入问题

例子:

  脚本代码如下: 
############################################## 

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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#!/usr/bin/expect 
#
#"设置超时"
set  timeout 5
 
 
#"传递变量"
set  warname [lindex $argv 0]
 
 
#"执行命令给变量赋值"
set  a [ exec  sudo  rpm -qa gitlab-ce]
 
 
 
#"spawn登录到主机"
spawn  /usr/bin/ssh  -p 22 -i  /home/ndnnd/test  test @172.18.10.160 
 
 
 
#"匹配交互字段,输入命令或密码"
expect  "*test':" 
#send "yes\r"
#expect "password:" 
#"发送命令\r结尾"
send  "12345\r"
expect  "*]$"
 
 
#"switch用法类似于case"
switch $warname {
             "zabbix-2.4.1.tar.gz"  {
                 send  "sudo scp root@172.18.10.236:/root/$warname /home/test\r"
                 expect  "*password:"
                 send  "tl0001010\r"
                 interact
             }
             "gitlab-ce-8.0.5-ce.0.el6.x86_64.rpm"  {
                                 send  "sudo scp root@172.18.10.236:/root/$warname /home/test\r"
                                 expect  "*password:"
                                 send  "tl0001010\r"
                                 interact 
                         }
             #"退出"
             "quit"  {
                                 send  "exit\r"
                                 expect eof
                                 exit
                         }
}
#"执行脚本"
#send "sudo /bin/bash /home/test/testssh.sh\r"
 
 
#"执行远程命令"
send  "sudo cat /etc/passwd\r"
 
#"if用法"
#if { $warname == "zabbix-2.4.1.tar.gz" } {
#send "sudo scp root@172.18.10.236:/root/$warname /home/test\r"
#expect "*password:"
#send "tl0001010\r"
#interact
#}else {
#   puts "SYNC error!"
#   exit 1
#}
 
#"类似echo用法"
puts  "--------------------------------------$a---------------------------------------"
send  "sudo /usr/sbin/nginx -s reload\r"
interact
 
 
################################################################################
expect eof 这个一定要加,与spawn对应表示捕获终端输出信息终止,类似于 if ....endif
expect脚本必须以interact或expect eof结束,执行自动化任务通常expect eof就够了。
设置expect永不超时
set  timeout -1
[interact] 
 
执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。如果你只是登录过去执行 
 
$argv 参数数组
 
expect脚本可以接受从 bash 传递过来的参数.可以使用[lindex $argv n]获得,n从0开始,分别表示第一个,第二个,第三个....参数
################################################################################
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
expect语法基础:  while for  循环、 if  语句的用法示例
 
==两种 for 循环的写法
for  { set  i 0} {$i<=10} {incr i} { #i默认增量是1,即等价incr i 1。注意这个反括号一定要写在这行行末:args: should be "for start test next command"
 
 
注:expect 用的是tcl语法,不是shell语法,或者用switch
== for /while 循环写法
     [15:33:05-Bob@hzling08:~ /test/tcl ]-(1109)No.108->$  cat  tclfor. test
     #!/usr/bin/expect --
     #                  http://bbs.chinaunix.net/thread-2301733-1-1.html
     # for Bob testing
     #
     puts  "---1---"
     for  { set  i 0} {$i < 10} {incr i} {
         puts  "I inside first loop: $i"
     }
 
     puts  "---2---"
     for  { set  i 3} {$i < 2} {incr i} {
         puts  "I inside second loop: $i"
     }
 
     puts  "---3---"
     puts  "Start"
     set  i 0
     while  {$i < 10} {
         puts  "I inside third loop: $i"
         incr i
         puts  "I after incr: $i"
     }
 
     set  i 0
     incr i
     puts  "---4---"
     puts  "$i"
     # This is equivalent to:
     set  i [ expr  {$i + 1}]     #expect里的加减法
     puts  "---5---"
     puts  "$i"
 
运行:
 
=== if 的写法
     if  { $sync_flag ==  "true"  } {
 
             puts  "Sync start at [clock format [clock seconds]]"
 
             catch { eval  exec  ${TOOL_HOME} /bin/ ${sync_cmd} ${sync_parm} } output
             puts $output
             if  { $output  eq  "SYNC complete!"  } {
                     puts  "SYNC complete!"
             else  {
                     puts  "SYNC error!"
                     exit  1
             }
 
             puts  "Sync end at [clock format [clock seconds]]"
     }
=== ping 的例子
set  p_loop 5
while  { $p_loop } {
     send_user  "\nStpe 1 Ping to server..."
     set  timeout 60
     send  "ping 10.1.1.1 -c5\r"
     expect {
         "64 bytes"  {
             send_user  "ok"
             set  p_loop 0
         }
      
         timeout {
             set  p_loop [ expr  $p_loop-1]   #expect里的加减法
             send_user  "failed.\n"
         }
         eof {
             send_user  "ping 10.1.1.1 -c5 FAIL\n"
             exit  1
         }
}
===expect读取文件的例子
#!/usr/bin/expect --
#            http://scmbob.org/counting_file_lines.html
#open a file
set  fd [ open  "/home/xiabao/myfile.txt"  r]
set  number 0
 
# read each line
while  { [gets $fd line] >= 0 } { incr number }
puts  "Number of lines: $number"
 
close $fd
 
==当前用户是root,我想用  su  - oracle,然后在oracle下使用 expect -c 命令,不想用脚本,想用一行命令实现
su  - oracle -c  "expect -c 'spawn sqlplus / as sysdba; expect \"SQL>\"; send \"alter user sys identified by 123456 account unlock;\r\"; send \"exit;\r\"'"


############################################## 

执行:

./test.sh那么就执行

基本框架
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.com 或 dir.exe 的可执行文件。
它主要的功能是给ssh运行进程加个壳,用来传递交互指令。 
4. [expect "password:"] 
这里的expect也是expect的一个内部命令,有点晕吧,expect的shell命令和内部命令是一样的,但不是一个功能,习惯就好了。这个命令的意思是判断上次输出结果里是否包含“password:”的字符串,如果有则立即返回,否则就等待一段时间后返回,这里等待时长就是前面设置的30秒
5. [send "ispass/r"] 
这里就是执行交互动作,与手工输入密码的动作等效。 
温馨提示: 命令字符串结尾别忘记加上“/r”,如果出现异常等待的状态可以核查一下。 
6. [interact] 
执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。如果你只是登录过去执行 



本文转自 吃草的青蛙 51CTO博客,原文链接:http://blog.51cto.com/tlinux/1735753,如需转载请自行联系原作者

相关文章
|
7天前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
6天前
|
Shell Linux
Linux shell编程学习笔记30:打造彩色的选项菜单
Linux shell编程学习笔记30:打造彩色的选项菜单
|
4天前
|
Shell Linux 开发工具
|
4天前
|
监控 Unix Shell
shell脚本编程学习
shell脚本编程
22 12
|
6天前
|
Shell Linux
Linux shell编程学习笔记82:w命令——一览无余
Linux shell编程学习笔记82:w命令——一览无余
|
1月前
|
存储 Unix Shell
shell脚本编程基础
【9月更文挑战第4天】
36 12
|
1月前
|
Shell Linux
Shell 编程 编写hello word
Shell 编写hello word
41 5
|
2月前
|
Shell KVM 虚拟化
Shell 数组编程
【8月更文挑战第22天】 Shell 数组编程
43 10
|
2月前
|
Shell 数据处理 C++
【震撼揭秘】Python正则VS Shell正则:一场跨越编程边界的史诗级对决!你绝不能错过的精彩较量,带你领略文本处理的极致魅力!
【8月更文挑战第19天】正则表达式是文本处理的强大工具,在Python与Shell中有广泛应用。两者虽语法各异,但仍共享许多基本元素,如`.`、`*`及`[]`等。Python通过`re`模块支持丰富的功能,如非捕获组及命名捕获组;而Shell则依赖`grep`、`sed`和`awk`等命令实现类似效果。尽管Python提供了更高级的特性和函数,Shell在处理文本文件方面仍有其独特优势。选择合适工具需根据具体需求和个人偏好决定。
29 1
|
2月前
|
监控 Shell Linux
探索Linux操作系统下的Shell编程之魅力
【8月更文挑战第4天】本文旨在通过一系列精心设计的示例和分析,揭示在Linux环境下进行Shell编程的独特之处及其强大功能。我们将从基础语法入手,逐步深入到脚本的编写与执行,最终通过实际代码案例展现Shell编程在日常系统管理和自动化任务中的应用价值。文章不仅适合初学者构建扎实的基础,同时也为有一定经验的开发者提供进阶技巧。
44 11