嵌入式系统那些事—脚本语言tcl

1 tcl脚本语言基本语法连接

        tcl脚本语言在嵌入式开发,通信设备开发调试中经常被用到。它是一种跟shell语言类似的解释型语言,不需要编译就可以运行,语法简单,作为程序员可以在几小时或者几天内就可以熟练掌握,但是它网络功能强大,又是开源免费的,因此在日常的网络设备调试,自动化测试,复现定位概率性问题中被广泛使用。

        参考文献【1】【2】的两个链接是tcl脚本的基本语法学习路径,笔者将其中重要的语法点总结如下图所示。图中上半部分是tcl的特点,下半部分是从文件和函数的视角对各个知识点的归类。

        tcl脚本文件的扩展名是tcl,针对文件相互之间的调用有package和source两种方式,package的方式使用比较复杂,笔者在ipop工具试验多次未成功,需要安装tclsh后才可以使用,退而求次之的解决方法是source的方式直接执行对应的文件。在tcl中的功能(函数)被称为过程,关键字是proc。在函数体内的实现,包含了11个关键属性,这些与其他的编程语言类似。作为一种特别擅长处理字符串的脚本语言,在其数据类型中包含了字符串的一系列命令,比如字符串的比较、去掉空白、子字符串的匹配等,这个部分在第2小节将详尽介绍。除此以外,像列表、数组、字典和句柄等数据类型也是tcl中常用的数据类型,并且有对应的处理命令,使用起来非常方便。tcl语言同样有自己的保留字,笔者统计大概有90个,同样有条件判断(决策)和循环这样的基本结构,在运算符上也支持算术、关系、逻辑、位等常见的表达式,对于文件的操作和读写也有自己的命令行,此处笔者不一一列举。

2 tcl脚本常用知识点

2.1 脚本间调用

        脚本文件之间可以相互调用,这样就可以将相同功能的测试用例放到一个tcl文件中,再通过统一的脚本调用接口调用,需要注意的是要做好测试用例之间的隔离,做好裁剪,减少依赖。假设有main.tcl和testcase.tcl两个脚本文件,main.tcl要调用执行testcase.tcl,testcase.tcl放在文件夹e2e中,路径结构如下:

---test

        ---main.tcl

        ---e2e

                ---testcase.tcl

                ---upgrade.tcl

        main.tcl对应的脚本代码如下:

#获取当前main.tcl脚本执行的路径

set path [pwd]

after 1000

...

#调用执行testcase.tcl

source “$path/e2e/testcase.tcl”

2.2 定时执行某个自动化脚本

        在实际的项目中,通常会定时跑某个自动化测试用例,比如定时在每天的凌晨2点进行自动化升级和跑测试用例。

#设置升级时间

set upgradeTime "02:00:00"

#一周7天,每天凌晨两点执行

for { set i 1} {$i < 604800} {incr i} {

    #获取当前的时间

    set currentTime [clock seconds]

    set localTime [clock format $currentTime -format %H:%M:%S]

    #未到达指定时间,延时1s后,继续循环执行

    if {[string compare $upgradeTime $localTime] != 0} {

        after 1000

        continue

    }

#已经是凌晨两点,则执行升级脚本

source “$path/e2e/upgrade.tcl”

#升级结束后,执行其他测试用例

...

}

2.3 与飞秋通信

        在完成自动化测试后,可以将自动化的结果保存到文件中,也可以将其即时通信给测试人员。tcl脚本语言支持tcp或者udp的socket通信方式,飞秋是一种可以在局域网内被广泛使用的即时通信工具,本身是通过udp的方式通信的,因此可以用tcl脚本语言将测试的结果通过飞秋发送给通信工具。具体的实现如下:

        a)由于udp包是tcl的扩展包,所以可以在sourceforge上下载udp1011-win32.zip,如下图所示,可以将udp1011-win32.zip下载下来,放到项目工程中。

        b)获取飞秋通信的IP地址和端口号,方法如下,首先是在任务管理器中找到飞秋的PID,图中所示PID为2728,然后在cmd命令行中输入netstat -ano,找到udp部分中PID为2728的,对应的IP地址为192.168.230.1,端口号为2425。

        c)打开ipop的报文捕获,捕获的IP地址是192.168.230.1,捕获的报文是UDP格式,然后通过飞秋发送一个helloworld,这样就可以获得刚才发送的飞秋报文的格式。飞秋报文的内容封装格式是:1:序列号:用户名:主机名:内容长度:helloworld。

        d)通过tcl脚本语言编写发送给飞秋的udp报文,详细的代码实现如下:

package require udp 1.0.11

#接收udp报文

proc recvPkt {sock} {

    global pkt

    global peer

    set pkt [read $sock]

    set peer [fconfigure $sock -peer]

    puts "received [string length $pkt] from $peer\n$pkt"

    return

}

#创建udp通信接口

proc createUdp {destIp destPort} {

    set s [udp_open $destPort]

    fconfigure $s -blocking 0 -buffering none -translation binary\

    -remote [list $destIp $destPort]

    fileevent $s readable [list recvPkt $s]

    return $s
}

#往飞秋发送消息

proc sendFeiQ {feiQInfo} {

    set destIp 192.168.230.1

    set destPort 2425

    set sock [createUdp $destIp $destPort]

    puts -nonewline $sock $feiQInfo

    close $sock

}

        e)调用上面的发送接口,发送消息

sendFeiQ "1:123:DESKTOP-9F0AJTV:DESKTOP-9F0AJTV:32:helloworld"

2.4 文件操作

        除了上面通过飞秋即时发送信息,还可以将测试的过程和结果记录到日志文件中,方便后续出现问题后快速定位,具体实现如下:

proc createFile {input} {

    set fp [open $input a+]

    return $fp

}

proc savelog {fp log} {

    puts $fp $log

    close $fp

}

set fp [createFile "input.txt"]

set log "helloworld"

savelog $fp $log

3 在ipop中执行tcl脚本语言

        tcl脚本除了安装tclsh执行以外,还可以在IPOP中执行,这个工具在嵌入式设备的调试中经常被使用,可以很方便的录制一些tcl的测试脚本,还提供了一些扩展语法,如tsend,msend等,在实际的项目开发中可以直接使用。

3.1 执行tcl脚本的环境 

        如下是tcl脚本的执行环境,在此处我们远程了一个linux虚拟机,在IPOP的TCL方式中导入事先写好的tcl脚本,然后选择执行所选,开始执行,就可以在这个界面中执行脚本。

3.2 发送命令后获取反馈信息

        此处我们选择msend这个扩展命令实现获取反馈信息。实现过程如下:

       1)语法:msend commandline string1 [timeout]

       2)使用场景:假设我们通过输入ifconfig获取ens33的ip地址192.168.179.136,如下所示。

# ifconfig

ens33 Link encap:Ethernet HWaddr 00:0c:29:55:7b:94

inet addr:192.168.179.136 Bcast:192.168.179.255 Mask:255.255.255.0

inet6 addr: fe80::d7c6:c558:4a60:84e6/64 Scope:Link

...

lo Link encap:Local Loopback

inet addr:127.0.0.1 Mask:255.0.0.0

inet6 addr: ::1/128 Scope:Host

...

        3)具体实现

proc getIpAddress {} {

    set str "lo"

    set Bcast "Bcast"

    set ret [msend "ifconfig" $str 5000]

    if {[string first $str $ret] > 0} {

        set index [string first $Bcast $ret]

        set len 17

        set firstIndex [expr $index - $len]

        set len 1

        set lastIndex [expr $index - $len]

        set ipAddr [string range $ret $firstIndex $lastIndex]

        tsend "$ipAddr"

        return $ipAddr

    }

    tsend "ip is abnormal"

    return "ERR"

}

getIpAddress

4 自动化测试脚本设计

        掌握了上面tcl基本的用法之后,就可以编写自己的自动化测试脚本,在日常的调试开发中,可以将经验性的问题定位思路和重复性的测试操作做成自动化的方式,提升工作效率。

        如下图所示是采用tcl脚本实现自动化测试的框架,我们选择ipop和飞秋两个工具。整个架构包括7个模块,分别是主入口模块,公共接口模块,配置模块,运行测试用例模块,分析测试结果,辅助定位错误和通知模块。

           各个模块功能如下:

  • 主入口模块:这个模块是整个自动化测试的入口,主要是对环境变量进行设置,对整个测试的流程进行控制,后续的各个模块的tcl文件,都在此处通过source的方式执行。
  • 公共接口模块:这个模块是后面各个模块可以使用的公共接口,像关于时间的或者关于日志记录的,都可以放到这个模块中。
  • 配置模块:这个模块实现一些初始化的配置信息,在这里可以定制自动化测试的开始时间,通信的方式等基本信息。
  • 运行测试用例:这个模块可以实现所有的测试用例的调用,用户自己设计的测试用例可以放置在此处统一调用,比如升级用例,版本检查用例等。
  • 分析测试结果:这个模块主要对前面的测试用例结果进行统计分析,包括有多少测试用例,通过了多少,失败了多少,这些信息会发送给飞秋。
  • 辅助定位错误:这个模块主要对测试用例中失败的模块进行辅助定位,确定可能的问题原因。
  • 通知模块:这个模块主要通过socket udp协议,往飞秋发送测试用例分析的结果和辅助定位的结果。

参考文献:

【1】Tcl-Tk教程

【2】tcl之文件操作-文件名相关 - CHIPER - 博客园

猜你喜欢

转载自blog.csdn.net/linus_ben/article/details/126687985