为BASH脚本导出系统日志文件创建进度条 [英] Creating a progress bar for BASH script exporting system log files
问题描述
基本上,对于一定数量的已提取和导出的系统日志,我需要通过打印字符#"来指示脚本的进度.这最终将创建一个宽度为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屋!