我希望在命令完成后得到如下所示的报告:
Start Time: 02/01/21 01:27pm
End Time: 02/01/21 02:29pm
Total Duration: 01 Hour 02 Minutes
我发现我可以使用 获取开始时间和结束时间date +"%d/%m/%y %I:%M%P"
。
例如,
start=$(date +"%d/%m/%y %I:%M%P")
start_duration=$(date +%s)
youtube-dl
end=$(date +"%d/%m/%y %I:%M%P")
end_duration=$(date +%s)
runtime=$((end_duration-start_duration))
echo "Start Time: ${start}"
echo "End Time: ${end}"
很少有问题。
- 我不明白如何打印
Total Duration: 01 Hour 02 Minutes
- 我怎样才能使这个脚本通用,以便我可以使用任何命令,而不仅仅是
youtube-dl
在这个脚本中。
我试过:
#! /bin/bash
Before=$(date +%s)
echo "$Before"
exec "$@"
ret=$?
After=$(date +%s)
echo "$After"
let Duration=After-Before
echo "$Duration"
if [[ $ret -eq 0 ]]
then
echo "Start Time: ${Before}"
echo "End Time: ${After}"
echo "Total Duration: ${Duration}"
return $ret
else
echo "Error: Command [ $@ ] returned $ret"
echo "Start Time: ${Before}"
echo "End Time: ${After}"
echo "Total Duration: ${Duration}"
return $ret
fi
但如果我使用它就不起作用ctrl+c
$ ./reporttime tail -f ~/.xsession-errors
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
^C
事实上,之后可能什么也没有执行exec "$@"
% ./reporttime cat reporttime
1609655953
#! /bin/bash
Before=$(date +%s)
echo "$Before"
exec "$@"
ret=$?
After=$(date +%s)
echo "$After"
let Duration=After-Before
echo "$Duration"
if [[ $ret -eq 0 ]]
then
echo "Start Time: ${Before}"
echo "End Time: ${After}"
echo "Total Duration: ${Duration}"
return $ret
else
echo "Error: Command [ $@ ] returned $ret"
echo "Start Time: ${Before}"
echo "End Time: ${After}"
echo "Total Duration: ${Duration}"
return $ret
fi%
答案1
和zsh
:
zmodload zsh/datetime
TIMEFMT='Total duration for %J: %*E'
preexec() strftime 'Start Time: %d/%m/%y %I:%M%P'
precmd() strftime 'End Time: %d/%m/%y %I:%M%P'
REPORTTIME=0
然后,您将在输入命令行时打印开始时间,在显示下一个提示之前打印结束时间,以及每个非内置命令的持续时间(更准确地说,对于 shell 等待的每个进程) :
$ sleep 1; sleep 2
Start Time: 02/01/21 08:31am
Total duration for sleep 1: 1.002
Total duration for sleep 2: 2.003
End Time: 02/01/21 08:31am
例如,您可以更改REPORTTIME=0
为REPORTTIME=10
仅报告占用 CPU 时间超过 10 秒的命令的时间(而不是过去time),或者为每个要计时的命令添加前缀time
.
作为需要任意命令来运行的脚本:
#! /bin/zsh -
zmodload zsh/datetime
TIMEFMT='Total duration: %*E'
strftime -s start 'Start Time: %d/%m/%y %I:%M%P'
{
duration=$(
exec 4>&2 2>&1 1>&3 3>&-
time "$@" 2>&4 4>&-
)
} 3>&1
ret=$?
strftime -s end 'End Time: %d/%m/%y %I:%M%P'
print -rlu2 $start $end $duration
exit $ret
进而:
$ ./reporttime sleep 65
Start Time: 02/01/21 09:26am
End Time: 02/01/21 09:26am
Total duration: 1:05.00
除了依赖time
,您还可以使用$SECONDS
或$EPOCHSECONDS
特殊变量(或者$EPOCHREALTIME
/$epochtime
如果您想要亚秒粒度)
#! /bin/zsh -
zmodload zsh/datetime
start=($epochtime)
"$@"
end=($epochtime) ret=$?
strftime >&2 'Start Time: %FT%T.%3.%z' $start
strftime >&2 'End Time: %FT%T.%3.%z' $end
printf >&2 'Total duration: %.3f\n' $((
end[1] - start[1] + (end[2] - start[2]) / 1e9
))
exit $ret
这次使用标准且明确的时间格式:
$ ./reporttime2 sleep 1
Start Time: 2021-01-02T09:50:49.261+0000
End Time: 2021-01-02T09:50:50.264+0000
Total duration: 1.003
如果您仍然想在按Ctrl+C或Ctrl+时报告这些计时\ ,否则会杀死两者zsh
以及正在计时的命令,您可以添加:
trap true INT QUIT
位于这些脚本的顶部,以便 shell 拦截这些信号并且不会死在那里。不要这样做trap '' INT QUIT
,这会导致信号被完全忽略,并且在这种情况下定时命令不会被终止。