首页 > 解决方案 > 为 BASH 脚本导出系统日志文件创建进度条

问题描述

基本上对于提取和导出的一组系统日志,我需要通过打印字符“#”来指示脚本进度。这最终应该会创建一个宽度为 60 的进度条。如下所示:#############################################另外,我需要从左到右构建字符,以指示脚本的进度。

此代码所基于的问题/问题如下:“使用单独的调用wevtutil el来获取日志数量的计数并将其缩放到例如 60 的宽度。”

SYSNAM=$(hostname)
LOGDIR=${1:-/tmp/${SYSNAM}_logs}

i=0
LOGCOUNT=$( wevtutil el | wc -l )
x=$(( LOGCOUNT/60 ))

wevtutil el | while read ALOG
do
        ALOG="${ALOG%$'\r'}"
        printf "${ALOG}:\r"
        SAFNAM="${ALOG// /_}"
        SAFNAM="${SAFNAM//\//-}"
        wevtutil epl "$ALOG" "${SYSNAM}_${SAFNAM}.evtx"


done

我尝试了诸如 using 之类的方法echo -ne "#"printf "#%0.s"但是我遇到的问题是“#”字符被打印在每个正在检索的日志文件名称的实例中;图案也是垂直印刷的,而不是水平印刷的。

LOGCOUNT=$( wevtutil el | wc -l )
x=$(( LOGCOUNT/60 ))

echo  -ne "["
for i in {1..60}
do
        if [[ $(( x*i )) != $LOGCOUNT ]]
        then
                echo -ne "#"
                #printf '#%0.s'
        fi

done
echo "]"
printf "\n"
echo "Transfer Complete."
echo "Total Log Files Transferred: $LOGCOUNT"

我之前尝试将此代码集成到第一个块中,但没有运气。但是有件事告诉我,我不需要建立一个全新的循环,我一直认为第一块代码只需要几行修改。无论如何,对于冗长的解释感到抱歉,如果需要任何其他帮助,请告诉我——谢谢。

标签: bashshellgit-bash

解决方案


为了这个答案,我将假设所需的输出是一个 2-liner,看起来像:

$ statbar
file: /bin/cygdbusmenu-qt5-2.dll
[########                            ]

以下可能不适用于每个人,因为它归结为各个终端属性以及它们如何(不)被tput(即ymmv)操纵......

对于我的示例脚本,我将遍历 的内容/bin,在处理它时打印每个文件的名称,同时在每 20 个文件之后使用新的“#”更新状态栏:

  • 我的下面有 719 个文件,/bin所以#'s我的状态栏中应该有 35 个(处理完成后我会在最后添加一个额外的文件#
  • 我们将使用一些tput命令来处理光标/行的移动,以及从一行中删除以前的输出
  • 为了打印状态栏,我预先计算了数量,#'s然后使用 2 个变量 ...$barspace用于空格,$barhash用于#'s; 对于每 20 个文件,我去掉一个空格$barspace并添加一个#$barhash; 通过每 20x 个文件(重新)打印这些 2x 变量,我得到一个移动状态栏的外观

把这一切放在一起:

$ cat statbar
clear              # make sure we have plenty of room to display our status bar;
                   # if we're at the bottom of the console/window and we cause the
                   # windows to 'scroll up' then 'tput sc/rc' will not work

tput sc            # save pointer/reference to current terminal line
erase=$(tput el)   # save control code for 'erase (rest of) line'

# init some variables; get a count of the number of files so we can pre-calculate the total length of our status bar

modcount=20
filecount=$(find /bin -type f | wc -l)

# generate a string of filecount/20+1 spaces (35+1 for my particular /bin)

barspace=

for ((i=1; i<=(filecount/modcount+1); i++))
do
        barspace="${barspace} "
done

barhash=           # start with no #'s for this variable

filecount=0        # we'll re-use this variable to keep track of # of files processed so need to reset

while read -r filename
do
        filecount=$((filecount+1))

        tput rc    # return cursor to previously saved terminal line (tput sc)

        # print filename (1st line of output); if shorter than previous filename we need to erase rest of line

        printf "file: ${filename}${erase}\n"

        # print our status bar (2nd line of output) on the first and every ${modcount} pass through loop; 

        if   [ ${filecount} -eq 1 ]
        then
                printf "[${barhash}${barspace}]\n"

        elif [[ $((filecount % ${modcount} )) -eq 0 ]]
        then
                # for every ${modcount}th file we ...

                barspace=${barspace:1:100000}         # strip a space from barspace
                barhash="${barhash}#"                 # add a '#' to barhash
                printf "[${barhash}${barspace}]\n"    # print our new status bar
        fi

done < <(find /bin -type f | sort -V)

# finish up the status bar (should only be 1 space left to 'convert' to a '#')

tput rc

printf "file: -- DONE --\n"

if [ ${#barspace} -gt 0 ]
then
        barspace=${barspace:1:100000}
        barhash="${barhash}#"
fi

printf "[${barhash}${barspace}]\n"

注意:在测试时,我必须定期重置终端以使tput命令正常运行,例如:

$ reset
$ statbar

我无法在任何(互联网)小提琴网站上使用上述内容(基本上在tput使用基于 Web 的“终端”时遇到问题)。

这是一个显示行为的 gif ...

在此处输入图像描述

笔记:

  • 该脚本确实将每个文件名打印到标准输出,但由于该脚本实际上并没有对有问题的文件做任何事情a)printfs发生得非常快,b)视频/gif只捕获(相对)少数转瞬即逝的图像(“Duh,Mark !”?)
  • 最后一个printf "file: -- DONE --\n"是在我创建 gif 之后添加的,我很懒惰,没有生成和上传新的 gif

推荐阅读