Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1237586
  • 博文数量: 389
  • 博客积分: 2874
  • 博客等级: 少校
  • 技术积分: 3577
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-24 10:34
文章分类

全部博文(389)

文章存档

2020年(2)

2018年(39)

2017年(27)

2016年(3)

2015年(55)

2014年(92)

2013年(54)

2012年(53)

2011年(64)

分类: 嵌入式

2013-11-20 17:31:13

本文章实现程序自动更新,思路是程序启动之前 检查文件服务器的程序版本,如果大于 当前版本就更新,否则直接运行当前程序。
服务器直接用ssh就可以,自动更新想到了expect,这里的方法是使用tcl+expect来实现的。

点击(此处)折叠或打开

  1. #!/usr/bin/tclsh
  2. package require Expect        #添加对expect的支持

  3. #获取服务器上的可更新 文件名
  4. #para:host 服务器 ip
  5. #para:服务器 用户名
  6. #para:服务器 密码
  7. proc version_f { host user key} {
  8.   set timeout 2
  9.   
  10.   if {[info exists host] == 0} {
  11.     send_user "remote update host ip is $host \n"
  12.     return
  13.   }
  14.   
  15.   #检查设置 user 和 key 的默认值
  16.   if {[info exists user] == 0} {
  17.     set user "root"
  18.   }

  19.   if {[info exists key] == 0} {
  20.     set key ""
  21.   }
  22.   
  23.   #获取文件名 ,感觉这个方法有点笨,但是一时还找不到其他方法 郁闷
  24.   #这里使用expect 的语法了
  25.   spawn ssh ${user}@${host} "cd ~/update;ls ~/update/exefile*>/tmp/version"
  26.   expect {
  27.     "yes/no" {
  28.                send "yes\r"
  29.      expect "password"
  30.      send "$key\r"
  31.              }
  32.     timeout { send_user "connect host timeout!"
  33.                return
  34.      }
  35.     "password" { send "$key\r"}
  36.     "Connection refused" {
  37.                            send_user "host $host Connection refused!"
  38.              return
  39.                          }
  40.   }
  41.   expect {
  42.     eof    {}
  43.     "Permission denied" {
  44.                           send_user "connect host auth failed!"
  45.              return
  46.                         }
  47.   }

  48.   #讲带有文件名的文件copy到本地
  49.   spawn scp ${user}@${host}:/tmp/version /tmp/version
  50.   expect {
  51.     timeout { send_user "connect host timeout!"
  52.                return
  53.      }
  54.     "password" { send "$key\r"}
  55.   }
  56.   expect eof

  57.   unset timeout
  58.   
  59.   #读取文件名,并返回
  60.   set f [open /tmp/version r]
  61.   gets $f line
  62.   set rnum [regexp {([a-z]+)[-_]([0-9]+)} $line str name index version]
  63.   close $f

  64.   if {$rnum == 0} {
  65.     return
  66.   }

  67.   #return $version
  68.   return $str
  69. }

  70. #判断是否需要更新版本
  71. #其实就是实现了一个比较,放到主程序里显得比较繁琐,所以封装
  72. #para: newvnum ,new version num
  73. proc need_update {newvnum} {
  74.   #获取当前目录下的可执行文件列表,这里的可执行文件格式是 exefile_[版本号]
  75.   set alist [glob exefile*]
  76.   if {[llength alist] == 0} {
  77.     puts "local agw can not exist!\n"
  78.     puts "update!\n"
  79.     return 1
  80.   }
  81.   
  82.   #用正则表达式获取版本号和文件名
  83.   regexp {exefile[-_]([0-9]+)} [lindex $alist 0] str index version
  84.   if {$version >= $newvnum} {
  85.     return 0;
  86.   }

  87.   return 1;
  88. }

  89. #获取服务器上的可更新 文件名
  90. #para:host 服务器 ip
  91. #para:user 用户名
  92. #para:key 密码
  93. #para:file 服务器上的文件名
  94. proc update {host user key file} {
  95.   #将本地文件 放到 bak 目录备份
  96.   set alist [glob exefile*]
  97.   foreach agw $alist {
  98.     file rename -force $agw ./bak/
  99.   }
  100.   #file rename -force exefile* ./bak/

  101.   #下载文件
  102.   set timeout 2
  103.   spawn scp ${user}@${host}:~/update/$file ./
  104.   expect {
  105.     timeout { send_user "connect host timeout!"
  106.                return 0
  107.      }
  108.     "password" { send "$key\r"}
  109.   }
  110.   expect eof

  111.   unset timeout
  112. }

  113. #运行文件
  114. proc run {} {
  115.   set alist [glob exefile*]

  116.   if {[llength alist] == 0} {
  117.     puts "local agw do not exist!\n"
  118.     return -1
  119.   }
  120.   #添加可执行权限,防止下载的文件没有权限
  121.   exec chmod a+x [pwd]/[lindex $alist 0]
  122.   #运行
  123.   exec [pwd]/[lindex $alist 0] &
  124. }

  125. #查看最新版本号
  126. set host 192.168.1.3
  127. set user root
  128. set key 111111
  129. #获取服务器上的文件名,如果获取失败直接执行本地文件
  130. set nname [version_f $host $user $key]
  131. if {[info exists nname] == 0} {
  132.   run
  133.   exit 0;
  134. }
  135. puts "server newest file: $nname"
  136. #更新文件,执行
  137. regexp {exefile[-_]([0-9]+)} $nname str index vers
  138. if {[need_update vers] == 1} {
  139.   puts "update...\n"
  140.   update $host $user $key $nname
  141. }

  142. run

部署
客户端部分:
普通浏览复制代码
  1. set host 192.168.1.3 
  2. set user root 
  3. set key  111111

是客户端对主机的配置,分别是主机ip 用户名和密码
需要将上面的脚本文件与可执行文件放到同一个目录,可执行文件的命名形式是access_****,后面的****是版本号,假设是/root/access。
然后修改/etc/rc.local,添加下面的代码:
cd /root/access
./update.tcl
客户端部分部署就结束了。
服务器部分:
待更新的程序放在:~/update/目录下,文件名的格式是 access_****,后面的****是版本号。
然后开启ssh服务,并且用户名密码需要和客户端的user和key匹配。
阅读(2347) | 评论(0) | 转发(0) |
0

上一篇:Zachman框架

下一篇:win7+codeblock 编译lua

给主人留下些什么吧!~~