自动交互的福音-Expect命令使用总结

自动交互的福音-Expect命令使用总结

[TOC]

现在智驾的运行环境很多不再是像之前的ADAS软件的运行平台,而是使用Linux或者是QNX式的RTOS系统.在这些系统上还没有类似Windows的那些成熟的工具软件可以使用,因此向域控制器中登录/传输数据时需要输入账号密码保证一定的安全性.Expect命令可以让我们从这令人厌烦的重复性操作解脱出来.本文总结以下使用的心得.

基本介绍

Expect是一个控制交互式程序的工具,用非交互的方式实现了所有交互式的功能.它是基于Tcl的.Tcl实际上是一个子程序库,这些子程序库可以嵌入到程序里从而提供语言服务. 最终的语言有点象一个典型的 Shell语言.里面有给变量赋值的set命令,控制程序执行的if,for,continue等命令,还能进行普通的数学和字符串操作.当然了,还可以 用exec来调用Unix程序.所有这些功能,Tcl都有.

安装

Ubuntu下(上位机),域控制器应该不需要安装.

1
sudo apt-get install tcl tk expect

源码安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sLengthExpect=`whereis expect`
if [ ${#sLengthExpect} -gt 8 ]; then
echo "expect command is found."
else
cp ./expect5.45.tar.gz /usr/local/src/
tar -xzvf ./tcl8.6.10-src.tar.gz /usr/local/src/
cd /usr/local/src/tcl8.6.10/unix
./configure
make
sudo make install
cd /usr/local/src/
tar -xzvf ./expect5.45.tar.gz /usr/local/src/
cd /usr/local/src/expect5.45
./configure
make
sudo make install
sudo ln -s /usr/local/bin/expect /usr/bin/expect
fi

启用选项

  • -c:执行脚本前先执行的命令,可多次使用.
  • -d:debug模式,可以在运行时输出一些诊断信息,与在脚本开始处使用exp_internal 1相似.
  • -D:启用交换调式器,可设一整数参数.
  • -f:从文件读取命令,仅用于使用#!时.如果文件名为”-“,则从stdin读取(使用”./-“从文件名为-的文件读取).
  • -i:交互式输入命令,使用”exit”或”EOF”退出输入状态.
  • --:标示选项结束(如果你需要传递与expect选项相似的参数给脚本时),可放到#!行:#!/usr/bin/expect --.
  • -v:显示expect版本信息.

常用命令

1
2
3
4
5
6
7
8
9
10
11
spawn               交互程序开始后面跟命令或者指定程序
expect 获取匹配信息匹配成功则执行expect后面的程序动作
send exp_send 用于发送指定的字符串信息
exp_continue 在expect中多次匹配就需要用到
send_user 用来打印输出 相当于shell中的echo
exit 退出expect脚本
eof expect执行结束 退出
set 定义变量
puts 输出变量
interact 恢复交互模式
set timeout 设置超时时间

使用案例

基本形式:

1
expect patlist1 action1 patlist2 action2.....

例子1,直接运行expect命令的脚本,test.sh,运行时./test.sh即可.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/expect
if {$argc < 3} {
send_user "Usage:\n $argv0 IPaddr User Passwd Port Passphrase\n"
puts stderr "argv error!\n"
sleep 1
exit 1
}
set IP [lindex $argv 0 ]
set user [lindex $argv 1 ]
set passwd [lindex $argv 2 ]

spawn ssh user@IP
expect "*password"
send "passwd\n"
expect eof

例子2,在bash环境里使用EOF代码块调用expect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
passwd='123456'
IP=192.168.1.1
user=USER

/usr/bin/expect <<-EOF
set timeout 5 #等待5s再执行下面的命令
spawn ssh $user@$IP
expect {
"*yes/no" { send "yes\r"; exp_continue } #接受多个匹配检查,并发送相应的字符串
"*password:" { send "$passwd\r" } #\r表示换行
}
expect eof
EOF

例子3,制作一个接受命令参数的函数,方便少输入代码.同时,expect是支持正则匹配的.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
passwd='123456'
IP=192.168.1.1
user=USER

expect_ssh(){
/usr/bin/expect<<-EOF
spawn bash -c "ssh -o StrictHostKeyChecking=no $user@$IP" #图方便,设置成最不安全的模式...
set timeout 1
expect "*password:*"
send "$gbSPassword\r"
expect "*#*" #假设新的一行命令行的开始符号为#
send "$1\r" #此处执行传入的命令参数
interact
expect eof
EOF
}

expect_ssh "cp to_be_copied_file $target_path" #向域控制器里copy文件

参考网址:http://xstarcd.github.io/wiki/shell/expect.html

自动交互的福音-Expect命令使用总结

https://www.chuxin911.com/expect_command_20211120/

作者

cx

发布于

2021-11-20

更新于

2022-07-16

许可协议