ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

linux-在Bash中显示长时间运行的应用程序的进度

2019-11-11 00:00:34  阅读:312  来源: 互联网

标签:bash progress installation linux


我有一些涉及嵌入式系统更新的程序,它们需要按顺序运行,并且需要向单独的系统报告进度.

这些阶段是:

>验证图像;
>将映像文件解压缩为活动磁盘上的文件;和
>将映像安装到备用磁盘.

之后,计算机将重新启动,备用磁盘将变为活动磁盘.

目前,我们报告的初始值为0%,验证结束时为5%,拆包结束时为45%,安装结束时为90%.重新启动后,当新映像开始运行时,将报告100%标记.

现在,尽管我对这种方法感到非常满意,但客户端希望看到更细粒度的更新状态报告.我们已经毫不含糊地让他们知道,此类报告大部分都是人为的,但他们认为有必要让客户满意.

因此,我正在寻找一种方法,可以根据粗糙的时间来报告进度,同时仍然要执行长时间运行的任务并完成工作.

我们知道,从开始到重新启动,整个安装过程大约需要两分钟,而在每个阶段花费的时间将按照给定的百分比分配.

解决方法:

在bash中执行此操作的一种方法是运行一个单独的过程来执行进度报告,并为其提供足够的信息以成功报告.这将涉及:

>起始百分比;
>期末百分比;
>要添加到每个周期的百分比的增量;和
>循环时间.

前两个很明显,它们提供了报告结果的上下限.

另外两个允许您提供报告比率.例如,每秒增加6%将使用这些值(增量= 6,周期= 1),并且每秒将增加6%.

对于较慢的步骤,例如每秒提供0.25%,您可以提供(增量= 1,周期= 4),每四秒钟将添加1%.您实际上并没有报告亚秒级的进度,只是随着时间的推移会平均得出该进度.

那么,这是怎么做的呢?首先,让我们提供一个简单的功能来报告进度.在您的情况下,应将其替换为用于与您提到的“独立系统”进行通信的任何内容.以下代码显示了如何执行此操作:

#!/usr/bin/env bash

doProgress() {
    # Simply echo progress using whatever was passed. Date is included
    # for debugging purposes.

    echo "$(date +%H:%M:%S): $1%"
}

解决方案的“实质”是backgroundReporter()函数,该函数将根据前面提到的四个参数调用doProgress():

backgroundReporter() {
    # Get the four parameters.

    currVal=$1 ; maxVal=$2 ; deltaVal=$3 ; timeGap=$4

    # If signalled to stop, output maximum percentage then exit.
    # Note no output if you've already reached the maximum.

    trap "[[ \${maxVal} -ne \${lastVal} ]] && doProg \${maxVal} ; exit" HUP

    # Infinite loop until signalled.

    while : ; do
        # Wait for the duration, save current percentage, and
        # calculate new percntage (capped at maximum).

        sleep ${timeGap}
        lastVal=${currVal}
        (( currVal = (currVal + deltaVal > maxVal) ? maxVal : currVal + deltaVal ))

        # Log only if it's changed.

        [[ ${currVal} -ne ${lastVal} ]] && doProg ${currVal}
    done
}

唯一棘手的是信号处理.在阶段完成后,将此功能作为后台任务运行的调用方负责向其发送信号.

当然,还有一些基本的测试用例可以证明这一点.首先,我们需要确保退出时杀死运行backgroundReporter()的子进程.当它不运行时执行以下命令:(一个简单的no-op)并杀死-HUP< pid>.运行时:

killCmd=":" ; trap "${killCmd}" EXIT

然后,我们报告初始进度为零,并开始三个阶段.它们比此处指定的问题短,因为这仅用于演示目的:

doProg 0

# 0 -> 10% at 4%/sec, phase takes six seconds.
bgReport 0 10 4 1 & killCmd="kill -HUP $!" ; sleep 6 ; ${killCmd} ; killCmd=":" ; wait

# 10 -> 20% at 1%/2secs, phase takes six seconds.
bgReport 10 20 1 2 & killCmd="kill -HUP $!" ; sleep 6 ; ${killCmd} ; killCmd=":" ; wait

# 20 -> 100% at 30%/sec, phase takes five seconds.
bgReport 20 100 30 1 & killCmd="kill -HUP $!" ; sleep 5 ; ${killCmd} ; killCmd=":" ; wait

而且,从样本运行中您可以看到,这三个阶段的工作非常符合您的期望(右边的评论是我的):

13:15:29: 0%
13:15:30: 4%      4% per sec
13:15:31: 8%
13:15:32: 10%     capped at 10% for remainder of 6-sec slot

13:15:37: 11%     goes up 1% per 2 secs
13:15:39: 12%
13:15:41: 20%     phase finishes, jumps immediately to max

13:15:42: 50%     goes up 30% per second
13:15:43: 80%
13:15:44: 100%    but capped at 100%

对于给定的实际时间,两分钟,其中阶段是5%的最终验证,45%的最终拆包和90%的最终安装,以下比较合适(阶段稍作修改,使比例更容易实现):

doProg 0

# Validation 0 -> 5%, 5 steps in 6 seconds (~ 1%/1s).
bgReport 0 5 1 1 & killCmd="kill -HUP $!"
validate
${killCmd} ; killCmd=":" ; wait

# Unpacking 5 -> 45%, 40 steps in 50 seconds (4%/5s).
bgReport 5 45 4 5 & killCmd="kill -HUP $!"
unpack
${killCmd} ; killCmd=":" ; wait

# Installing 45 -> 95%, 50 steps in 64 seconds (~ 5%/6s)
bgReport 45 95 5 6 & killCmd="kill -HUP $!"
install
${killCmd} ; killCmd=":" ; wait

有了这些比率,您可以保证每(最多)六秒钟获得一次进度更新,这与原始方法不同,原始方法是将其停留在45%的状态持续一分钟,然后立即跳至95%.

标签:bash,progress,installation,linux
来源: https://codeday.me/bug/20191110/2016193.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有