日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

shell進度條追蹤指令執行時間的場景分析_linux shell

作者:農民工老王 ? 更新時間: 2022-08-07 編程語言

最近一兩年,我經手了不少與shell相關的工作。在這個過程中,我越發覺得shell腳本在完成具體任務的同時,應該再給用戶展示一個進度條,用以提示當前階段還需要多少時間才能完成。

linux中的不少軟件都有進度條,比如yum的軟件安裝過程,docker的鏡像拉取過程。本想借鑒這些軟件的進度條的實現方法,但其開發語言大都不是shell,我就只好作罷。隨后,我在網上搜索shell進度條的實現方法,而找到的大都是用for或while循環在控制臺上直接打印等號或箭頭,并在循環體中用sleep命令實現一個固定的停頓,因而進度條完成的時間是固定的,而且在打印進度條時也沒有實現具體任務。那種進度條是完全沒有意義的。

于是,我就自己實現了一個shell進度條,測試表明實現了既定目標。可以追蹤指令的執行時間。如果在預定用時之前完成,那么進度條會接到通知,然后立刻跑完剩余進度;如果指令的運行用時超出預定時間,那么進度條會在96%的地方等待指令跟上,然后再跑完剩余的4%。

本文中的進度條可以應用于大部分場景。不用修改進度條函數的任何代碼,就可以直接使用。特別適合那些可預估指令執行時間的場景。對于如下載、文件復制等可以準確地計算出進度數值的情況,也可以基本滿足,還可以參考本文的思路,修改進度條函數,進而顯示精確的進度數值。

代碼

代碼如下:

#!/bin/bash
progressBarTempPath=$(mktemp)
echo "0" >"$progressBarTempPath"
progressBar () {
  local time=$1
  local interval=1
  if [[ "${time}" == *"s" ]]; then
    interval=$(echo "scale=5;${time//s/}/60"|bc)
  elif [[ "${time}" == *"m" ]]; then
    interval=${time//m/}
  else
    echo "進度條參數錯誤"
    return 1
  fi
  local nowNum=1
  local str=''
  local postfix=('/' '-' '\' '|')
  while [ $nowNum -le 100 ]; do
    local needEnd=`cat "$progressBarTempPath"`
    local index=$((nowNum%4))
    printf "[%-50s %-3d%% %c]\r" "$str" "$nowNum" "${postfix[$index]}"
    nowNum=$((nowNum+1))
    if [ $needEnd -eq 1 ]; then
        sleep 0.1
    else
      if  [ $nowNum -le 20 ] ; then
          sleep  $interval
      elif [  $nowNum -gt 95  ];then
          local nowNumCopy=$nowNum
          while [ $needEnd -eq 0 ]; do
              sleep $interval
              local innerIndex=$(((nowNumCopy+1)%4))
              printf "[%-50s %-3d%% %c]\r" "$str" "$nowNum" "${postfix[$innerIndex]} "
              needEnd=$(cat "$progressBarTempPath")
              nowNumCopy=$((nowNumCopy+1))
          done
      else
          sleep $(echo "scale=5;${interval}/2"|bc)
      fi
    fi
    if (($nowNum % 2 == 0)); then
      str+='='
    fi
  done
  printf "\n"
}
# 多線程調用進度條函數,參數表示預估的大概時間。參數中的s表示時間單位秒,還可以用m表分鐘。
progressBar 20s &
# 調用進度條后,就是完成具體操作的代碼。
echo "模擬一個24秒執行完成的任務。"
sleep 24
# 通知進度條函數完成進度
echo "1" >"$progressBarTempPath"
wait

使用說明

使用非常簡單,按照以下兩步操作即可。

  • 將代碼中的第56、57行換成您實際需要執行的命令。最好屏蔽其運行過程中的輸出。
  • 將代碼中第53行的方法調用參數20s換成你預估的實際時間。

效果展示

原文鏈接:https://blog.csdn.net/monarch91/article/details/124788554

欄目分類
最近更新