显示每秒运行bash脚本的已用时间

时间:2021-10-31 16:21:53

I'm running a shell script in Linux Mint that calls some processes taking few minutes. For each process I want to echo a message like this:

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

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

where X is the current elapsed time and I would like it to change every second, but not printing a new line.

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

Is there a good way to do that? I only found ways to print the total time in the end, but not the elapsed time while running the process.

有没有一个好方法呢?我只找到了最终打印总时间的方法,但没有找到运行流程时经过的时间。

4 个解决方案

#1


8  

Use this at the beginning of your script, this creates a subprocess which runs in background and keeps on updating the status.

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

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

#2


1  

You can run each command with time:

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

time <command>

and then use sed/awk to exctract the elapsed time.

然后使用sed / awk来消除经过的时间。

#3


1  

You'll have to run the process in the background with &, otherwise the rest of the script will wait until it finishes. Use backspaces to overwrite your current line, so make sure you don't use newlines.

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

So, to do what you want:

所以,做你想做的事:

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

#4


0  

Here is a way to have awk print on STDERR every seconds. You should just add:

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

  • when myprocess is over, create a file /tmp/SOMETHING
  • 当myprocess结束时,创建一个文件/ tmp / SOMETHING

  • have awk include a test : it exits when /tmp/SOMETHING appears
  • awk包含一个测试:当/ tmp / SOMETHING出现时它会退出

The loop part (without the termination test... so "infinite loop" until CTRL-C) is:

循环部分(没有终止测试......所以“无限循环”直到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" }'

now you just need to use "printf" and ansi escape sequence to print without a newline, have the ansi-escape go back until the beginning of the number, and flush the output (all descriptors) by invoking system:

现在你只需要使用“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("") }'

note: this is compatible with all version of awk I know of, even ANCIENT ones (ie, not gawk/nawk only, but also the venerable awk.)

注意:这与我所知道的所有awk版本都兼容,即使是古代版本的awk(也就是说,不仅仅是gawk / nawk,还有古老的awk。)

#1


8  

Use this at the beginning of your script, this creates a subprocess which runs in background and keeps on updating the status.

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

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

#2


1  

You can run each command with time:

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

time <command>

and then use sed/awk to exctract the elapsed time.

然后使用sed / awk来消除经过的时间。

#3


1  

You'll have to run the process in the background with &, otherwise the rest of the script will wait until it finishes. Use backspaces to overwrite your current line, so make sure you don't use newlines.

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

So, to do what you want:

所以,做你想做的事:

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

#4


0  

Here is a way to have awk print on STDERR every seconds. You should just add:

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

  • when myprocess is over, create a file /tmp/SOMETHING
  • 当myprocess结束时,创建一个文件/ tmp / SOMETHING

  • have awk include a test : it exits when /tmp/SOMETHING appears
  • awk包含一个测试:当/ tmp / SOMETHING出现时它会退出

The loop part (without the termination test... so "infinite loop" until CTRL-C) is:

循环部分(没有终止测试......所以“无限循环”直到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" }'

now you just need to use "printf" and ansi escape sequence to print without a newline, have the ansi-escape go back until the beginning of the number, and flush the output (all descriptors) by invoking system:

现在你只需要使用“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("") }'

note: this is compatible with all version of awk I know of, even ANCIENT ones (ie, not gawk/nawk only, but also the venerable awk.)

注意:这与我所知道的所有awk版本都兼容,即使是古代版本的awk(也就是说,不仅仅是gawk / nawk,还有古老的awk。)