之前有写mysql数据导入进度查看, 现在又想看下其它比较耗时的进度了, 比如查看tar解压的剩余时间, 虽然解压通常很快(顺序IO), 但有个时间, 尤其是进度条 会显得很高大上 -_-
其实主要是顺便改进下脚本, 支持多个进程的进度查看.
还是和之前一样的, 查看当前的 /proc/PID/io
的rchar
然后除以总大小, 就得到进度了. 剩余大小再除以速度就是剩余时间了.
又区别的就是, 我们可以使用如下命令查看 压缩包解压后的大小.
gzip
gzip -l /root/mysql-5.7.43-linux-glibc2.12-x86_64.tar.gz
xz
xz -l /root/mysql-8.0.33-linux-glibc2.12-x86_64.tar.xz
由于我们要支持多个进度条同时显示, 我们就要固定进度条的位置(行号). 可以使用 ANSI escape code来定位光标,并打印进度条. 还是来看时间演示例子吧.
这里同时解压 xz 和 gz 文件 , 方便观察
tar -xvf mysql-5.7.43-linux-glibc2.12-x86_64.tar.gz
tar -xvf mysql-8.0.33-linux-glibc2.12-x86_64.tar.xz
然后使用本脚本(见文末)来观察进度
sh tar_gz_or_xz_progress_view.sh
我们可以看到 gzip 压缩率比 xz高, 解压速度还更快. 建议使用gzip来压缩
我们就可以动态的看到解压进度了. 那么这有啥用呢? 没啥用, 光是花里胡哨的. 不, 这可以让我们的终端看起来更酷. 写脚本的时候, 就可以把这个脚本带上, 让我们的其它脚本也花里胡哨的更优雅.
github地址: https://github.com/ddcw/ddcw/blob/master/shells/tar_gz_or_xz_progress_view.sh
tar_gz_or_xz_progress_view.sh 也可以见如下:
直接使用, 不需要参数. SLEEP_INTERNAL
表示每隔多少秒显示一次. 就是显示频率
#!/usr/bin/env bash
#write by ddcw @https://github.com/ddcw
# tar.gz/tar.xz 解压进度查看脚本
export LANG="en_US.UTF-8"
SLEEP_INTERNAL=0.1
jindutiao2(){
PID=$1
lineno=$2
PRONAME=`cat /proc/${PID}/comm`
FILENAME=`ls -l /proc/${PID}/fd/0 | awk '{print $NF}'`
SOURCE_SIZE=`stat -c "%s" ${FILENAME} | awk '{size = $1; if (size < 1024) { printf "%.2f B\n", size } else if (size < 1024 * 1024) { printf "%.2f KiB\n", size / 1024 } else if (size < 1024 * 1024 * 1024) { printf "%.2f MiB\n", size / 1024 / 1024 } else { printf "%.2f GiB\n", size / 1024 / 1024 / 1024 } }'`
if [ "${PRONAME}" == "xz" ];then
DEST_SIZE="`xz -l ${FILENAME} | tail -1 | awk '{print $5,$6}'`"
elif [ "${PRONAME}" == "gzip" ];then
DEST_SIZE="`gzip -l ${FILENAME} | tail -1 | awk '{print $2}' | awk '{size = $1; if (size < 1024) { printf "%.2f B\n", size } else if (size < 1024 * 1024) { printf "%.2f KiB\n", size / 1024 } else if (size < 1024 * 1024 * 1024) { printf "%.2f MiB\n", size / 1024 / 1024 } else { printf "%.2f GiB\n", size / 1024 / 1024 / 1024 } }'`"
else
break
fi
TOTAL_SIZE=`stat -c '%s' ${FILENAME}`
CURRENT_SIZE=0
OLD_SIZE=`awk '{ if ($1=="rchar:") print $2}' /proc/${PID}/io 2>/dev/null`
START_TIME=`date +%s`
CURRENT_RATE="0 B/s"
#不使用 kill -0 pid , 怕审计不过...
while [ ${CURRENT_SIZE} -lt ${TOTAL_SIZE} ] && [ -d /proc/${PID} ];do
CURRENT_SIZE=`awk '{ if ($1=="rchar:") print $2}' /proc/${PID}/io 2>/dev/null`
TIME_DIFF="$[ $(date +%s) - ${START_TIME} ]"
if [ "${CURRENT_SIZE}" == "" ];then
break
fi
if [ ${TIME_DIFF} -gt 0 ];then
CURRENT_RATE=`echo "${OLD_SIZE} ${CURRENT_SIZE} ${TIME_DIFF}" | awk '{print ($2-$1)/$3}' | awk '{size = $1; if (size < 1024) { printf "%.2f B/s\n", size } else if (size < 1024 * 1024) { printf "%.2f KiB/s\n", size / 1024 } else if (size < 1024 * 1024 * 1024) { printf "%.2f MiB/s\n", size / 1024 / 1024 } else { printf "%.2f GiB/s\n", size / 1024 / 1024 / 1024 } }'`
REST_TIME=`echo "${TOTAL_SIZE} ${CURRENT_SIZE} ${TIME_DIFF} ${OLD_SIZE}" | awk '{print ($1-$2)/(($2-$4)/$3)}' | awk '{printf "%.2f seconds\n",$1}'`
else
CURRENT_RATE="0 B/s"
REST_TIME="0"
fi
filled_len=$((CURRENT_SIZE * 50 / ${TOTAL_SIZE}))
bar=$(printf "%-${filled_len}s" "#" | sed 's/ /#/g')
spaces=$(printf "%-$((50-filled_len))s" "")
echo -ne "\033[${lineno};0H${PID}: |$bar$spaces| $[ ${CURRENT_SIZE} * 100 / ${TOTAL_SIZE} ]% RATE:${CURRENT_RATE} THE_REST_TIME:${REST_TIME} "
sleep ${SLEEP_INTERNAL}
done
echo -e "\033[${lineno};0H${PID}: Done ${FILENAME} RATE:${CURRENT_RATE} COMM:${PRONAME} ${SOURCE_SIZE} --> ${DEST_SIZE}"
}
PIDS=(`pidof gzip`)
PIDS+=(`pidof xz`)
if [ -z ${PIDS} ];then
echo "NO gzip or xz is Running. "
exit 1
fi
current_no=0
clear
for pid in ${PIDS[@]};do
((current_no++))
jindutiao2 ${pid} ${current_no} &
done
wait
exit 0
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。