博客主页:https://tomcat.blog.csdn.net
博主昵称:农民工老王
主要领域:Java、Linux、K8S
期待大家的关注💖点赞👍收藏⭐留言💬
目录
最近一两年,我经手了不少与shell相关的工作。在这个过程中,我越发觉得shell脚本在完成具体任务的同时,应该再给用户展示一个进度条,用以提示脚本执行完成还需要多少时间。
Linux中的不少软件都有类似功能,比如yum的安装过程,docker的镜像拉取过程。本想借鉴这些软件的进度条的实现方法,但这些软件的开发语言大都不是shell脚本,我就只好作罢。
然后,我在网上搜索shell进度条的实现方法,而找到的大都是用for或while循环在控制台上直接打印等号或箭头,在循环体中用sleep命令实现一个固定的停顿,因而进度条完成的时间是固定的,而且在打印进度条时也没有实现具体任务。那种进度条是完全没有意义的。
于是我设计了一个进度条,测试表明实现了既定目标。可以在完成具体操作的过程中,反馈实际进度。如果在预定用时之前完成,那么进度条会接到通知,迅速跑完;如果脚本的运行用时超出预定时间,那么进度条会在96%的地方等待程序跟上,然后再跑完剩余进度。
代码
代码如下:
#!/bin/bashprogressBarTempPath=$(mktemp)echo"0">"$progressBarTempPath"progressBar(){localtime=$1localinterval=1if[["${time}"== *"s"]];theninterval=$(echo"scale=5;${time//s/}/60"|bc)elif[["${time}"== *"m"]];theninterval=${time//m/}elseecho"进度条参数错误"return1filocalnowNum=1localstr=''localpostfix=('/''-''\''|')while[$nowNum -le 100];dolocalneedEnd=`cat"$progressBarTempPath"`localindex=$((nowNum%4))printf"[%-50s %-3d%% %c]\r""$str""$nowNum""${postfix[$index]}"nowNum=$((nowNum+1))if[$needEnd -eq 1];thensleep0.1elseif[$nowNum -le 20];thensleep$intervalelif[$nowNum -gt 95];thenlocalnowNumCopy=$nowNumwhile[$needEnd -eq 0];dosleep$intervallocalinnerIndex=$(((nowNumCopy+1)%4))printf"[%-50s %-3d%% %c]\r""$str""$nowNum""${postfix[$innerIndex]} "needEnd=$(cat"$progressBarTempPath")nowNumCopy=$((nowNumCopy+1))doneelsesleep$(echo"scale=5;${interval}/2"|bc)fifiif(($nowNum %2==0));thenstr+='='fidoneprintf"\n"}# 多线程调用进度条函数,参数表示预估的大概时间。参数中的s表示时间单位秒,还可以用m表分钟。
progressBar 20s &# 调用进度条后,就是完成具体操作的代码。echo"模拟一个24秒执行完成的任务。"sleep24# 通知进度条函数完成进度echo"1">"$progressBarTempPath"wait
使用说明
使用非常简单,按照以下两步操作即可。
- 将代码中的第56、57行换成您实际需要执行的命令。最好屏蔽其运行过程中的输出。
- 将代码中第53行的方法调用参数
20s
换成你预估的实际时间。
效果展示
如需转载,请注明本文的出处:农民工老王的CSDN博客https://blog.csdn.net/monarch91 。
版权归原作者 农民工老王 所有, 如有侵权,请联系我们删除。