メインコンテンツへスキップ

zshでコマンドの実行時刻と実行時間を計測する

·1 分·
Makoto Morinaga
著者
Makoto Morinaga
技術メモ、コーディング、環境構築のための個人ノート。
目次

zsh上で、「このコマンドをいつ実行したか?」、「処理が終わったのは何時頃で、どれくらいかかったか?」 という情報を後から確認したくなることがあります。

そのため、この記事で以下の2点を用いてターミナル画面に時間情報を残す方法を紹介します。

  • Enterを押すたびに、プロンプト「実行時刻」を記録
  • コマンドの「実行時間」を自動で計測し、長時間実行された場合のみ通知

Enterのタイミングで「実行時刻」をプロンプトに記録する
#

以下を~/.zshrcに追記します。

function _date_exec {
    PROMPT="[%D{%Y/%m/%d} %*] %~ %# "
    zle .reset-prompt
    zle .accept-line
}

zle -N accept-line _date_exec

関数の処理の流れ
#

  1. Enterを押下する
  2. 指定したフォーマット(最左に「押下した時刻」を付与した形式)にプロンプトにリセットする
  3. その直後にコマンドを実行する

実行例
#

[2025/12/30 12:46:54] ~ % cd scripts
[2025/12/30 12:46:57] ~ % git pull

これで画面をスクロールするだけで「いつ実行したか」が分かります。

すでにプロンプトをカスタマイズしている場合の注意点
#

_date_execは毎回プロンプトを上書きします。

そのため、既存のプロンプトを設定している場合は上書きされてしまうので、既存のプロンプトの内容を_date_exec内に統合してください。

以下は統合する場合の例です。

# 既存のPROMPT(例です)
PROMPT="%n@%m:%~ %# "

# _date_execに統合(実行日時と既存プロンプトを統合)
function _date_exec {
    PROMPT="[%D{%Y/%m/%d} %*] %n@%m:%~ %# "
    zle .reset-prompt
    zle .accept-line
}

実行時間を自動計測し、長時間実行された場合のみ通知する
#

こちらも~/.zshrcに以下を追記します。

function format_duration() {
    local total_seconds=$1
    local hours=$(( total_seconds / 3600 ))
    local minutes=$(( (total_seconds % 3600) / 60 ))
    local seconds=$(( total_seconds % 60 ))

    if (( hours > 0 )); then
        echo "${hours}h ${minutes}m ${seconds}s"
    elif (( minutes > 0 )); then
        echo "${minutes}m ${seconds}s"
    else
        echo "${seconds}s"
    fi
}

function _time_and_date_precmd() {
    local timer_end=$SECONDS
    local duration=$(( timer_end - TIMER_START ))
    local current_time=$(date +"%Y-%m-%d %H:%M:%S")

    if [[ -n "$TIMER_START" && "$duration" -gt 300 ]]; then
        local formatted_duration=$(format_duration $duration)
        printf "\nCommand finished at %s, took %s\n" "$current_time" "$formatted_duration"
    fi

    TIMER_START=""
}

function _time_and_date_preexec() {
    TIMER_START=$SECONDS
}

add-zsh-hook preexec _time_and_date_preexec
add-zsh-hook precmd _time_and_date_precmd

処理の流れ
#

  1. 任意のコマンドを実行する(Enter を押したタイミングで、preexecが呼ばれる)。
  2. preexecによってコマンド開始時刻をTIMER_STARTに記録
  3. コマンドが終了したタイミングでprecmdが呼ばれ、処理時間を計算
  4. 処理時間が5分以上(300秒以上)の場合のみ開始時刻・終了時刻・経過時間を通知
  5. TIMER_STARTをリセットする

実行例
#

[2025/12/30 10:35:22] make

Command finished at 2025-12-30 12:46:35, took 2h 11m 13s

これで目を離していても、実行時間・終了時間・経過時間がターミナル画面を見るだけで分かります。

関連記事