美文网首页
FOTA差分包编译服务器搭建

FOTA差分包编译服务器搭建

作者: chenwr2018 | 来源:发表于2019-06-14 14:04 被阅读0次

    奈何公司测试组电脑没有Linux系统,每次测试FOTA升级用的差分包都需要找我来制作,实在麻烦。本想搞个QT界面弄得专业点,后面有时间再去搞吧,现在打算先临时写一个应急。


    image

    一、Ubuntu端先搭建FTP服务器

    参考之前搭建的记录
    Ubuntu14.04搭建FTP服务器记录 - chenwr2018的博客 - CSDN博客 https://blog.csdn.net/chenwr2018/article/details/90512929

    因为还没实现多人同时制作差分包的功能,为了保证编译过程中不受影响,服务端限制了客户端的连接数。
    保证当前服务器只有一个IP连接,并且一个IP只有2个客户端连接数,一个用来上传文件,一个用来下载。
    只需在vsftpd.conf中添加,重启服务即可。
    max_clients=2
    max_per_ip=1

    二、Inotify工具

    Inotify 是一个 Linux特性,它监控文件系统操作,比如读取、写入和创建。Inotify 反应灵敏,用法非常简单,并且比 cron 任务的繁忙轮询高效得多。

    1.安装Inotify工具

    sudo apt-get install inotify-tools

    2.参数说明

    inotifywait

    语法:
    inotifywait [-hcmrq] [-e ] [-t ] [--format ] [--timefmt ] [ ... ]
    参数:
    -h,--help
    输出帮助信息
    @
    排除不需要监视的文件,可以是相对路径,也可以是绝对路径。
    --fromfile 
    从文件读取需要监视的文件或排除的文件,一个文件一行,排除的文件以@开头。
    -m, --monitor
    接收到一个事情而不退出,无限期地执行。默认的行为是接收到一个事情后立即退出。
    -d, --daemon
    跟--monitor一样,除了是在后台运行,需要指定--outfile把事情输出到一个文件。也意味着使用了--syslog。
    -o, --outfile 
    输出事情到一个文件而不是标准输出。
    -s, --syslog
    输出错误信息到系统日志
    -r, --recursive
    监视一个目录下的所有子目录。
    -q, --quiet
    指定一次,不会输出详细信息,指定二次,除了致命错误,不会输出任何信息。
    --exclude 
    正则匹配需要排除的文件,大小写敏感。
    --excludei 
    正则匹配需要排除的文件,忽略大小写。
    -t , --timeout 
    设置超时时间,如果为0,则无限期地执行下去。
    -e , --event 
    指定监视的事件。
    -c, --csv
    输出csv格式。
    --timefmt 
    指定时间格式,用于--format选项中的%T格式。
    --format 
    指定输出格式。
    %w 表示发生事件的目录
    %f 表示发生事件的文件
    %e 表示发生的事件
    %Xe 事件以“X"分隔
    %T 使用由--timefmt定义的时间格式
    

    inotifywatch

    语法:
    inotifywatch [-hvzrqf] [-e ] [-t ] [-a ] [-d ] [ ... ]
    参数:
    -h, --help
    输出帮助信息
    -v, --verbose
    输出详细信息
    @
    排除不需要监视的文件,可以是相对路径,也可以是绝对路径。
    --fromfile 
    从文件读取需要监视的文件或排除的文件,一个文件一行,排除的文件以@开头。
    -z, --zero
    输出表格的行和列,即使元素为空
    --exclude 
    正则匹配需要排除的文件,大小写敏感。
    --excludei 
    正则匹配需要排除的文件,忽略大小写。
    -r, --recursive
    监视一个目录下的所有子目录。
    -t , --timeout 
    设置超时时间
    -e , --event 
    只监听指定的事件。
    -a , --ascending 
    以指定事件升序排列。
    -d , --descending 
    以指定事件降序排列。
    
    可监听事件
    access  文件读取
    modify  文件更改。
    attrib  文件属性更改,如权限,时间戳等。
    close_write 以可写模式打开的文件被关闭,不代表此文件一定已经写入数据。
    close_nowrite   以只读模式打开的文件被关闭。
    close   文件被关闭,不管它是如何打开的。
    open    文件打开。
    moved_to    一个文件或目录移动到监听的目录,即使是在同一目录内移动,此事件也触发。
    moved_from  一个文件或目录移出监听的目录,即使是在同一目录内移动,此事件也触发。
    move    包括moved_to和 moved_from
    move_self   文件或目录被移除,之后不再监听此文件或目录。
    create  文件或目录创建
    delete  文件或目录删除
    delete_self 文件或目录移除,之后不再监听此文件或目录
    unmount 文件系统取消挂载,之后不再监听此文件系统。
    

    3.实际测试

    Ubuntu端

    root@chenwr-pc:/home# inotifywait -rm /home/workspace/project/Build_FOTA/EC20-delta-gentools
    Setting up watches.  Beware: since -r was given, this may take a while!
    Watches established.
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v1/ OPEN 666
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v1/ MODIFY 666
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v1/ MODIFY 666
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v1/ CLOSE_WRITE,CLOSE 666
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ OPEN 233
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ MODIFY 233
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ MODIFY 233
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ CLOSE_WRITE,CLOSE 233
    

    PC端

    发送文件至Ubuntu端FTP服务器

    E:\windows_to_linux_FTP
    ftp> open 192.168.1.35
    连接到 192.168.1.35。
    220 (vsFTPd 3.0.2)
    200 Always in UTF8 mode.
    ftp> user FTP
    331 Please specify the password.
    
    230 Login successful.
    ftp> put 1.zip /home/workspace/project/Build_FOTA/EC20-delta-gentools/v1/666
    200 PORT command successful. Consider using PASV.
    150 Ok to send data.
    226 Transfer complete.
    ftp: 发送 252 字节,用时 0.00秒 252000.00千字节/秒。
    ftp> put 1.zip /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/233
    200 PORT command successful. Consider using PASV.
    150 Ok to send data.
    226 Transfer complete.
    ftp: 发送 252 字节,用时 0.00秒 252.00千字节/秒。
    ftp>
    

    保存日志
    inotifywait -rm /home/workspace/project/Build_FOTA/EC20-delta-gentools | tee /var/log/ftp_message
    后续直接通过管道来逐行读取就好,就没必要写到文件中。主要目的是判断FTP接受文件完毕。

    使用该监控文件变化会出现一个问题,PC端FTP传输数据都是小块小块的传输

    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ MODIFY 233
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ MODIFY 233
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ MODIFY 233
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ MODIFY 233
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ MODIFY 233
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ MODIFY 233
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ MODIFY 233
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ CLOSE_WRITE,CLOSE 233
    

    所以脚本执行的条件还是判断关键语句吧
    /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ CLOSE_WRITE

    三、完整的demo

    1.ubuntu端shell脚本

    测试代码:
    auto_build_fota.sh

    #!/bin/sh
    sleep 5 # wait server start
    BUILD_FOTA="/home/workspace/project/Build_FOTA/EC20-delta-gentools"
    SCRIPT="./update_gen.sh a"
    content1="/home/workspace/project/Build_FOTA/EC20-delta-gentools/v1/ CLOSE_WRITE,CLOSE targetfiles.zip"
    content2="/home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ CLOSE_WRITE,CLOSE targetfiles.zip"
    flag=0;
    log=$BUILD_FOTA/log
    echo "start auto build fota script" > $log
    /usr/bin/inotifywait -rm $BUILD_FOTA \
    | while read line
    do
        if [ "$line" = "$content1" ]; then
            echo $(data)
            echo $line >> $log
            echo "recv targetfiles.zip suc from client pc" >> $log
            flag=1
        fi
        if [ "$line" = "$content2" ] && [ $flag = 1 ] ; then
            flag=0
            echo $line >> $log
            cd $BUILD_FOTA
            echo "cur path $(pwd)" >> $log
            echo "start build time: $(date)" >> $log
            $SCRIPT 2>&1 | tee -a $log
            if [ $? != 0 ]; then
                echo "Build Script run failded!" >> $log
            else
                echo "Build Script run success!" >> $log
                echo "Build end time: $(date)" >> $log
                cp $BUILD_FOTA/mainapp* $BUILD_FOTA/bak
                echo "60 sec after to delete mainapp_fota" >> $log
                sleep 60
                rm -f $BUILD_FOTA/mainapp*
                if [ $? != 0 ]; then
                    echo "mainapp delete failed" >> $log
                else
                    echo "mainapp delete success" >> $log
                fi
            fi
        fi
    done
    

    /usr/bin/inotifywait -rm $BUILD_FOTA | while read line
    逐行读取监控目录的信息,一旦有新文件产生会有信息产生。通过判断关键语句/home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/ CLOSE_WRITE,得出该文件FTP传输结束,紧接着触发编译脚本。

    设置该脚本开机自启
    简单在/etc/rc.local文件中添加要启动的脚本

    image

    2.PC端bat脚本

    (1)auto_build_fota.bat脚本

    @echo off
    title mainapp_fota差分包编译工具
    mode con lines=20 cols=55
    color 3f
    echo.
    echo             请不要关闭此窗口,耐心等待!!!
    echo.
    
    set file1=1.zip
    set file2=2.zip
    set ftplog=ftp_log
    set ftpfilename=ftp.cfg
    
    set b=%cd%
    echo %b%
    if exist %file1% (
        if exist %file2% (
            echo 文件上传中......
            goto ftp_upload
        ) else (
            echo %file2% is not exist!
            pause
            exit
        )
    ) else (
        echo %file1% is not exist!
        pause
        exit
    )
    
    :ftp_upload
    echo open 192.168.1.35>"%ftpfilename%" 
    echo user ftp>>"%ftpfilename%" 
    echo 123456>>"%ftpfilename%"
    echo.>>"%ftpfilename%"
    echo put %file1% /home/workspace/project/Build_FOTA/EC20-delta-gentools/v1/targetfiles.zip>>"%ftpfilename%"
    echo put %file2% /home/workspace/project/Build_FOTA/EC20-delta-gentools/v2/targetfiles.zip>>"%ftpfilename%"  
    echo bye >>"%ftpfilename%" 
    ftp -n -s:"%ftpfilename%" >"%ftplog%" 
    del "%ftpfilename%"
    
    find %ftplog% "Failed to establish connection" > C:\null
    if "%errorlevel%"=="0" (
        goto firewall_error
    ) else (
        echo targetfiles.zip 文件上传成功!
        echo.
        goto progress_bar_compile
        pause
    )
    goto:eof
    
    
    :ftp_download
    echo open 192.168.1.35>"%ftpfilename%" 
    echo user ftp>>"%ftpfilename%" 
    echo 123456>>"%ftpfilename%"
    echo.>>"%ftpfilename%"
    echo mget /home/workspace/project/Build_FOTA/EC20-delta-gentools/mainapp* >>"%ftpfilename%"
    echo.>>"%ftpfilename%"
    echo bye >>"%ftpfilename%" 
    ftp -n -s:"%ftpfilename%" >>"%ftplog%"
    del "%ftpfilename%"
    find %ftplog% "mainapp_" > C:\null
    IF ERRORLEVEL 1 goto download_error
    echo mainapp_fota 文件下载成功!
    pause
    goto:eof
    
    :progress_bar_compile
    cls
    set a=^set /p=■^<nul^&ping/n 2 127.1^>nul^&
    echo.
    echo   正在编译中...... 
    echo.
    echo ┌──────────────────────────────────────┐
    set/p=  <nul&%a%%a%%a%%a%%a%%a%%a%%a%%a%%a%%a%%a%%a%%a%%a%%a%%a%%a%%a%%a%
    echo    100%%
    echo └──────────────────────────────────────┘
    echo 编译成功!!!
    goto ftp_download
    pause
    goto:eof
    
    :upload_error
    echo 文件上传失败
    pause
    goto:eof
    
    :firewall_error
    echo 请关闭windows防火墙后,重新运行脚本。
    pause
    goto:eof
    
    :download_error
    echo 获取mainapp_fota失败,请重新运行脚本。
    pause
    goto:eof
    
    echo.
    pause
    
    

    (2)脚本简单说明

    1.mode con lines=20 cols=55 是设置你批处理运行时窗口大小的

    2.使用了 @echo off 之后就无需再用 @;命令前加@符号,表示不显示@后面的命令。举一个不和谐的例子:在入侵过程中(使用批处理来格式化敌人的硬盘)自然不能让对方看到你使用的命令啦。

    3.FTP参数说明

    FTP [-v] [-d] [-i] [-n] [-g] [-s:filename] [-a] [-A] [-x:sendbuffer] [-r:recvbuffer] [-b:asyncbuffers] [-w:windowsize] [host]
    
      -v              禁止显示远程服务器响应。
      -n              禁止在初始连接时自动登录。
      -i              关闭多文件传输过程中的
                      交互式提示。
      -d              启用调试。
      -g              禁用文件名通配(请参阅 GLOB 命令)。
      -s:filename     指定包含 FTP 命令的文本文件;命令
                      在 FTP 启动后自动运行。
      -a              在绑字数据连接时使用所有本地接口。
      -A              匿名登录。
      -x:send sockbuf 覆盖默认的 SO_SNDBUF 大小 8192。
      -r:recv sockbuf 覆盖默认的 SO_RCVBUF 大小 8192。
      -b:async count  覆盖默认的异步计数 3
      -w:windowsize   覆盖默认的传输缓冲区大小 65535。
      host            指定主机名称或要连接到的远程主机
                      的 IP 地址。
    
    注意:
      - mget 和 mput 命令将 y/n/q 视为 yes/no/quit。
      - 使用 Ctrl-C 中止命令。
    

    将FTP相关ip密码等信息写入文件中,再通过-s参数去实现命令自动运行。

    4.echo.为换行,因mget会可以模糊从FTP服务器上传输文件,如果FTP服务器存在多个前缀相同的文件时此时就需要回车来确认,因此需要记得mget语句写入文件后再增加个echo.

    5.程序返回码 echo %errorlevel%
    每个命令运行结束,可以用这个命令行格式查看返回码
    用于判断刚才的命令是否执行成功
    默认值为0,一般命令执行出错会设 errorlevel 为1
    if "%errorlevel%"=="0" (
    goto firewall_error
    ) else (
    echo No Run
    )

    6.bat乱码问题,在文件右键用“编辑”打开, 另存为时,UTF-8保存为ANSI格式。即可解决运行是乱码问题。

    7.pc端将FTP运行结果保存到文件中,可通过对文件的关键字来判断FTP的运行状态。

    (3)BAT脚本如何判断文件是否存在?

    SET file1=1.zip
    SET file2=2.zip
    echo 文件上传中......
    set b=%cd%
    echo %b%
    if exist %file1% (
        echo %file1% is exist!
    ) else (
        echo %file1% is not exist!
    )
    if exist %file2% (
        echo %file2% is exist!
    ) else (
        echo %file2% is not exist!
    )
    

    (4)bat如何编写函数

    bat 脚本之 使用函数 - caopeng的专栏 - CSDN博客 https://blog.csdn.net/peng_cao/article/details/73999076

    格式
    :func
    函数内部动作
    goto:eof

    实例

    @echo off
    @title copy sth to current filepath
    mode con lines=5 cols=40
    
    SET SourceFile=1.zip
    SET GenFile1=2.zip
    
    if exist %SourceFile% (
        if not exist %GenFile1% (
            echo %GenFile1% is no exist!
            call:hello
        ) else (
            echo %GenFile1% is exist!
        )
    ) else (
        echo %SourceFile% is not exist!
    )
    
    :hello
    echo hello world
    pause
    goto:eof
    echo Success
    ping -n 3 127.0.0.1 > nul
    pause
    

    使用call会继续执行一次函数,goto就不会。

    image

    (5)bat脚本for循环

    指定次数循环
    FOR /L %variable IN (start,step,end) DO command [command-parameters]
    组合命令:
    FOR /L %variable IN (start,step,end) DO (
    Command1
    Command2
    ……
    )

    (6)进度条简单实例

    (现在还不清楚进度条如何同步,正在编译的状态暂时按照时间来计时。)

    @echo off
    cls
    set a=^set /p=■^<nul^&ping/n 1 127.1^>nul^&
    
    echo.
    echo   正在编译中...... 
    echo.
    echo ┌──────────────────────────────────────┐
    :cycle
    for %%i in (■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■) do (set/p=<nul&%a% goto jindu)
    goto:eof
    echo    100%%
    echo └──────────────────────────────────────┘
    echo 编译成功!!!
    pause
    :jindu
    
    goto cycle
    goto:eof
    
    

    四、参考资料

    bat批处理修改cmd窗口大小、标题、字体、背景颜色 - zj0910 - CSDN博客 https://blog.csdn.net/zj0910/article/details/46942861

    .bat文件中call命令的用法 - 村长 - CSDN博客 https://blog.csdn.net/a_little_a_day/article/details/78243518

    在程序里调用ftp批处理(sh)上传文件,如何判断文件已成功上传-CSDN论坛 https://bbs.csdn.net/topics/80459535

    利用windows系统ftp命令编写的BAT文件上传[转] - 风之语 - BlogJava http://www.blogjava.net/gf7/archive/2010/07/21/326690.html

    FTP返回值详解 - pgmsoul的专栏 - CSDN博客 https://blog.csdn.net/pgmsoul/article/details/6384731

    [转]Bat脚本处理ftp超强案例解说 - 是谁啊? - 博客园 http://www.cnblogs.com/hanxianlong/p/5497663.html

    bat命令入门与高级技巧详解DOS/BAT脚本之家 https://www.jb51.net/article/97204.htm

    inotify-tools使用方法介绍 - wangkangluo1 - 博客园 http://www.cnblogs.com/wangkangluo1/p/3685587.html

    Linux下的文件更新触发同步 - kenyon的个人页面 - OSCHINA https://my.oschina.net/Kenyon/blog/177265

    FTP命令详解(含操作实例) - IndexMan的专栏 - CSDN博客 https://blog.csdn.net/indexman/article/details/46387561

    mget命令, ftp命令详解 - wajika - 博客园 https://www.cnblogs.com/wajika/p/6484420.html

    相关文章

      网友评论

          本文标题:FOTA差分包编译服务器搭建

          本文链接:https://www.haomeiwen.com/subject/imoufctx.html