将命令的执行时间存储在变量中

时间:2014-10-19 17:54:30

标签: bash time

我正在尝试为命令行编写任务运行器。没有理由。只是想这样做。基本上它只运行一个命令,将输出存储在一个文件(而不是stdout)中,同时在stdout上输出各种类型的进度指示器,当它们全部完成时,打印Completed ($TIME_HERE)

以下是代码:

#!/bin/bash
task() {
  TIMEFORMAT="%E"
  COMMAND=$1
  printf "\033[0;33m${2:-$COMMAND}\033[0m\n"
  while true
  do
    for i in 1 2 3 4 5
    do
      printf '.'
      sleep 0.5
    done
    printf "\b\b\b\b\b     \b\b\b\b\b"
    sleep 0.5
  done &
  WHILE=$!
  EXECTIME=$({ TIMEFORMAT='%E';time $COMMAND >log; } 2>&1)
  kill -9 $WHILE
  echo $EXECTIME
  #printf "\rCompleted (${EXECTIME}s)\n"
}

我承认,有一些不必要的奇特位。但是我经历了大量的StackOverflow问题来做不同类型的花哨的东西只是来尝试一下。如果要在任何地方使用,可以切断很多脂肪。但事实并非如此。

它被称为:

task "ping google.com -c 4" "Pinging google.com 4 times"

它的作用是以黄色打印Pinging google.com 4 times,然后在下一行打印一段时间。然后每隔0.5秒打印另一个时间段。五个句点之后,从同一行的开头开始并重复此操作直到命令完成。然后它应该打印Complete ($TIME_HERE)(显然)执行命令代替$TIME_HERE所花费的时间。 (我已经评论过,当前版本只打印时间)。

问题

问题在于,不是执行时间,而是打印出一些非常奇怪的东西。这可能是我正在做的蠢事。但我不知道问题的起源。这是输出。

$ sh taskrunner.sh 
Pinging google.com 4 times
..0.00user 0.00system 0:03.51elapsed 0%CPU (0avgtext+0avgdata 996maxresident)k 0inputs+16outputs (0major+338minor)pagefaults 0swaps

在终端中运行COMMAND='ping google.com -c 4';EXECTIME=$({ TIMEFORMAT='%E';time $COMMAND >log; } 2>&1);echo $EXECTIME按预期工作,即打印出时间(在我的情况下为3.559秒)。

我已检查过,/bin/shdash的符号链接。 (但这应该不是问题,因为我的脚本在/bin/bash中按照顶部的shebang运行。)

我希望在解决此问题的同时学习,因此解释的解决方案会很酷。谢谢。 :)

1 个答案:

答案 0 :(得分:2)

使用以下命令调用脚本时

 sh scriptname

脚本将传递给sh(在您的情况下为dash),这将忽略shebang行。 (在shell脚本中,shebang是一个注释,因为它以#开头。这不是巧合。)

Shebang行仅针对作为命令启动的命令进行解释,因为它们由系统的命令启动程序解释,而不是由shell解释。


顺便说一句,您调用time并未正确地将time内置输出与timed命令可能发送到stderr的任何输出分开。我认为你会更好:

EXECTIME=$({ TIMEFORMAT=%E; time $COMMAND >log.out 2>log.err; } 2>&1)

但这还不够。尝试将命令放入字符串变量时,您将继续遇到标准问题,即只能使用非常简单的命令。请参阅Bash FAQ。或者看看其中一些答案:

(或者可能有数百个其他类似的答案。)