6

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

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

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

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

4

4 回答 4

9

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

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
于 2013-06-03T12:37:27.913 回答
1

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

time <command>

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

于 2013-06-03T12:09:53.037 回答
1

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

所以,做你想做的事:

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
于 2013-06-03T12:27:56.300 回答
0

这是一种每秒在 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。)

于 2013-06-03T12:47:34.280 回答