【问题标题】:Show elapsed time every second running a bash script每秒显示运行 bash 脚本的经过时间
【发布时间】:2013-06-03 12:08:03
【问题描述】:

我在 Linux Mint 中运行一个 shell 脚本,它调用一些需要几分钟的进程。 对于每个进程,我想回显这样的消息:

echo "Cleaning temporary files... X seconds."
myprocess

其中 X 是当前经过的时间,我希望它每秒更改一次,但不打印新行。

有什么好的方法吗?我最终只找到了打印总时间的方法,但没有找到运行进程时经过的时间。

【问题讨论】:

标签: linux bash shell


【解决方案1】:

在脚本的开头使用它,这将创建一个在后台运行并不断更新状态的子进程。

file=$(mktemp)
progress() {
  pc=0;
  while [ -e $file ]
    do
      echo -ne "$pc sec\033[0K\r"
      sleep 1
      ((pc++))
    done
}
progress &
#Do all the necessary staff

#now when everything is done
rm -f $file

【讨论】:

  • 将输出生成器置于后台并继续在前台工作的好方法!
  • 但是如果脚本的其余部分的任何输出出现在屏幕上,一切都会搞砸:) 在我看来,这需要一个基于dialog 的完整脚本来处理所有场景。但这似乎有点工作
  • 也许如果我有其他输出,处理这两个输出可能会很棘手,但幸运的是这不是我的情况,这很好,谢谢abasu :)
  • 欢迎,实际上,rm -f $file 将在脚本的末尾,我更新了答案:)
【解决方案2】:

您可以随时间运行每个命令:

time <command>

然后使用 sed/awk 提取经过的时间。

【讨论】:

    【解决方案3】:

    您必须使用&amp; 在后台运行该进程,否则脚本的其余部分将等待它完成。使用退格键覆盖您的 current 行,因此请确保不要使用换行符。

    所以,做你想做的事:

    myproc &
    myPid=$!  # save process id
    tmp=""
    while true; do
        if kill -0 "$myPid"; then  # if the process accepts a signal, keep waiting
             for i in {0..${#tmp}..1}; do
                 printf "%b" "\b" # print backspaces until we have cleared the previous line
             done
             tmp=$( printf "Cleaning temp files... %t seconds." )
             printf "%s" "$tmp"
         else
             break # drop out of the while loop
         fi
         sleep 1
    done
    

    【讨论】:

    • 已经很不错了。你为什么不使用回车,\r 代替?要考虑不同的文本长度,您可以打印一些额外的空格。它更干净。你也忘了在你的循环中睡觉。
    • @ypnos 我保留了我的字符串,所以我可以得到长度和退格,不需要额外的空格。我相信\r\n有同样的问题,不过他有兴趣可以测试一下。顺便说一句,感谢您注意到缺少的睡眠。
    【解决方案4】:

    这是一种每秒在 STDERR 上打印 awk 的方法。 你应该添加:

    • 当 myprocess 结束时,创建一个文件 /tmp/SOMETHING
    • 让 awk 包含一个测试:当 /tmp/SOMETHING 出现时它退出

    循环部分(没有终止测试......所以“无限循环”直到 CTRL-C)是:

     ping 127.0.0.1 | awk '
         BEGIN{cmd="date +%s"; cmd|getline startup ; close (cmd) } 
         /bytes from/ { cmd | getline D ; close (cmd) ; 
                        print D-startup | "cat >&2" }'
    

    现在您只需要使用“printf”和 ansi 转义序列即可在没有换行符的情况下打印,让 ansi-escape 返回到数字的开头,并通过调用系统刷新输出(所有描述符):

     ping 127.0.0.1 | awk -v getback4char="$(printf '\033[4D')"  '
     BEGIN{cmd="date +%s"; cmd|getline startup ; close (cmd) ; printf "Elapsed time: ";}
     /bytes from/ { cmd | getline D ; close (cmd) ;
                    printf "%4d%s" ,(D-startup) , getback4char | "cat >&2"
                    system("") }'
    

    注意:这与我所知道的所有 awk 版本兼容,甚至是 ANCIENT 版本(即,不仅是 gawk/nawk,还包括古老的 awk。)

    【讨论】:

    • 抱歉 printf 上的错字,现在它又可以工作了(并显示“已用时间”)
    猜你喜欢
    • 2012-05-01
    • 2020-06-07
    • 2014-09-29
    • 2021-05-10
    • 1970-01-01
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多