嵌入式 Linux 系统在线升级策略架构

2019-07-12 14:38发布

https://www.ibm.com/developerworks/cn/linux/1712_anxiang_online_upgrade_strategy/index.html?ca=drs-&utm_source=tuicool&utm_medium=referral 由于市面上大多数嵌入式设备的分散、数量庞大、部署地点情况复杂,因此对于这些设备进行个体、本地升级的实施非常费时费力。针对这种现状,本文提供一种对基于 Linux 系统的嵌入式设备进行在线、远程、批量升级的策略,通过 web 页面对设备状态、升级过程可视化展示,大大提供升级效率。

嵌入式 Linux 系统在线升级策略

对于运行 Linux 系统的嵌入式产品,很多时候我们发现了当前版本内核、驱动、或者应用程序的 bug 并对之修复之后,或者研发出了功能更丰富、性能更突出的应用软件时,想要对当前运行的设备进行相应程序替换和升级。很多人的做法是通过对每一台设备烧写新版软件的方式进行软件版本更新,如果产品数量少且分布地点比较集中,这种方案具有一定的实效性。但是当设备数量庞大且地点分散时,这种本地烧写的升级方式将会变得非常难以操作,且升级结果可视化具有一定难度,需要通过串口等终端才能确认。 针对采用 Linux 系统且具有互联网接入能力的嵌入式设备,不论这种接入方式是有线网络、wifi、2G 或者 4G,本文将为其提供一种通过服务端后台对在线的所有或者部分设备进行远程批量升级的高效、可靠、直观的升级策略。升级内容可以是内核、驱动、文件系统、应用程序或者某些配置文件。接下来,将首先展示该方案的架构图,紧接着一步步讲述各个功能或者逻辑模块的细节。

方案概述

此升级方案由后台服务端程序、web 页面、终端升级程序三部分组成。如图 1 展示了升级方案 的架构图。
图 1. 升级方案架构图

服务端程序

服务端程序用来监测终端设备状态,管理升级包,升级流程控制并且提供 web 端响应以及数据库访问。本策略中的服务端为 apache-tomcat,程序采用 java servlet,数据库为 MySQL,web 页面为 JSP 编写。您可以使用任何一种后台语言(如 php、python 等)实现本文所描述的服务端功能。 服务端功能有:
  • 终端消息处理
  • 升级包管理
  • 升级指令处理

终端消息处理

服务端程序通过 getParameter("version")获得终端软件版本号,通过 queryLatestVersion()查询数据库中最新软件版本号,然后将二者进行对比。如果相同,则证明该终端设备软件版本已经是最新,返回 latest 指令;如果不同且服务端没有收到 web 端用户的升级指令,则通过 queryAddress()从数据库中查询最新升级包的地址,将之返回给终端,以便终端设备从该地址下载升级包,另外,如果此时用户在 web 界面执行了升级命令,则返回 update 指令给终端,终端设备执行升级操作。详细请查看清单 1。
清单 1. 终端消息处理代码片段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {     String msg = null;     String version_latest = null;     String address_latest = null;     String version = request.getParameter("version");       PrintWriter out = response.getWriter();     version_latest = queryLatestVersion();     if(version.equals(version_latest)){         msg = "|latest|null|null|";     }else if(UpdateServlet.update_status){         msg = "|update|"+version_latest+"|null|";         UpdateServlet.update_status = false;     }else{         address_latest = queryAddress();         msg = "|download|172.x.x.x"+address_latest+"|"+MD5+"|";     }     out.print(msg);     out.flush();     out.close(); }

升级包管理

服务端程序处理 web 端上传的升级包,首先确认存放升级包的路径是否存在,没有则创建。升级包接收完成之后,从升级包文件名中截取版本号,然后将文件名、版本号、升级包在服务端的存放路径信息插入到数据库中。类似的,服务端程序也响应 web 端用户对升级包的更改、删除等操作。详细的升级包管理请查看清单 2。
清单 2. 升级包管理代码片段
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 protected void doPost(HttpServletRequest request,     HttpServletResponse response) throws ServletException, IOException {     String uploadPath = "/xx/xx";     File uploadDir = new File(uploadPath);     if (!uploadDir.exists()) {         uploadDir.mkdir();     }     try {     List<FileItem> formItems = upload.parseRequest(request);     if (formItems != null && formItems.size() > 0) {          for (FileItem item : formItems) {              if (!item.isFormField()) {                  String fileName = new File(item.getName()).getName();                  Patternp=Pattern.compile("update_package-(.*?).tar.gz");                  Matcherm=p.matcher(fileName);                  while(m.find()){                      version = m.group(1);                  }                 String filePath = uploadPath + File.separator + fileName;                 sql = "INSERT INTO package(name,version,address)                 VALUES('"+fileName+"','"+version+"','"+filePath+"');";                 dbOperate(sql);                 File storeFile = new File(filePath);                 item.write(storeFile);                 request.setAtt