为BASH脚本导出系统日志文件创建进度条 [英] Creating a progress bar for BASH script exporting system log files

查看:101
本文介绍了为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

我尝试了使用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"

我以前尝试将此代码集成到第一个块中,但是没有运气.但是有些事情告诉我,我不需要建立一个全新的循环,我一直认为第一段代码只需要修改几行即可.抱歉,冗长的解释,如果需要其他帮助,请告诉我-谢谢.

解决方案

为了这个答案,我将假设所需的输出是一个类似以下内容的2-liner:

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

以下内容可能不适用于每个人,因为它取决于各个终端属性以及tput(即ymmv)如何(或不可以)操纵它们的属性...

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

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

将所有内容放在一起:

$ cat statbar
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 in $(seq 1 $(( ${filecount} / ${modcount} + 1 )) )
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 ...

注意:

  • 脚本确实将每个文件名打印到stdout,但是由于该脚本实际上并未对所涉及的文件执行任何操作a)printfs发生得很快,并且b)仅视频/gif捕获(相对)一些稍纵即逝的图像("Duh,Mark!"?)
  • 最后一个printf "file: -- DONE --\n"是在创建gif之后添加的,而我懒于不生成和上传新的gif

Essentially for a set number of systems logs pulled and exported I need to indicate the scripts progress by printing a character "#". This should eventually create a progress bar with a width of 60. Something like what's presented below: ############################################# ,additionally I need the characters to build from left to right indicating the progression of the script.

The Question/Problem that this code was based off of goes as follows: "Use a separate invocation of wevtutil el to get the count of the number of logs and scale this to,say, a width of 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

I've attempted methods such as using echo -ne "#", and printf "#%0.s" however the issue that I encounter is that the "#" characters gets printed with each instance of the name of the log file being retrieved; also the pattern is printed vertically rather than horizontally.

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"

I tried previously integrating this code into the first block but no luck. But something tells me that I don't need to establish a whole new loop, I keep thinking that the first block of code only needs a few lines of modification. Anyhow sorry for the lengthy explanation, please let me know if anything additional is needed for assistance--Thank you.

解决方案

For the sake of this answer I'm going to assume the desired output is a 2-liner that looks something like:

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

The following may not work for everyone as it comes down to individual terminal attributes and how they can(not) be manipulated by tput (ie, ymmv) ...

For my sample script I'm going to loop through the contents of /bin, printing the name of each file as I process it, while updating the status bar with a new '#' after each 20 files:

  • there are 719 files under my /bin so there should be 35 #'s in my status bar (I add an extra # at the end once processing has completed)
  • we'll use a few tput commands to handle cursor/line movement, plus erasing previous output from a line
  • for printing the status bar I've pre-calculated the number of #'s and then use 2 variables ... $barspace for spaces, $barhash for #'s; for each 20 files I strip a space off $barspace and add a single # to $barhash; by (re)printing these 2x variables every 20x files I get the appearance of a moving status bar

Putting this all together:

$ cat statbar
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 in $(seq 1 $(( ${filecount} / ${modcount} + 1 )) )
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"

NOTE: While testing I had to periodically reset my terminal in order for the tput commands to function properly, eg:

$ reset
$ statbar

I couldn't get the above to work on any of the (internet) fiddle sites (basically having problems getting tput to work with the web-based 'terminals').

Here's a gif displaying the behavior ...

NOTES:

  • the script does print every filename to stdout but since this script isn't actually doing anything with the files in question a) the printfs occur quite rapidly and b) the video/gif only captures a (relatively) few fleeting images ("Duh, Mark!" ?)
  • the last printf "file: -- DONE --\n" was added after I created the gif, and I'm being lazy by not generating and uploading a new gif

这篇关于为BASH脚本导出系统日志文件创建进度条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆