コマンド完了後の持続時間、開始時間、終了時間

コマンド完了後の持続時間、開始時間、終了時間

コマンドが完了したら、次のレポートを受けたいと思います。

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}"

問題はほとんどありません。

  1. 印刷する方法がわかりません。Total Duration: 01 Hour 02 Minutes
  2. 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

次に、コマンドラインを入力すると、開始時刻、次のプロンプトが表示される前の終了時刻、および組み込まれていない各コマンドの期間(より正確にはシェルが待機する各プロセスについて)が印刷されます。

$ 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

たとえば、CPU時間が10秒以上かかるコマンドの時間だけを報告するようにREPORTTIME=0変更できます。REPORTTIME=10過去時間)または時間を測定する各コマンドの前にプレフィックスを付けます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

依存関係に加えて、特殊変数(または/ 1秒未満の粒度が必要な場合)を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

シェルがこれらのシグナルを傍受してそこから死ぬのを防ぐために、このスクリプトの一番上にあります。これをしないでくださいtrap '' INT QUIT。信号が完全に無視され、この場合、タイムアウトコマンドは終了しません。

おすすめ記事