65

最後のコマンドの経過壁時間をBashプロンプトに埋め込む方法はありますか?私はこのように見える何かを望んでいます:

[last: 0s][/my/dir]$ sleep 10
[last: 10s][/my/dir]$

バックグラウンド

私は頻繁に長いデータ処理ジョブを実行しますが、それらがどれくらいの時間を要したかを知ることは有用です。そうすれば、将来のジョブにかかる時間を見積もることができます。非常に定期的なタスクの場合、私は先に進み、適切なロギング手法を使用してこの情報を厳密に記録します。あまり形式的でないタスクの場合は、コマンドの前に。を付けますtime

timeすべてのインタラクティブコマンド を自動的に実行し、タイミング情報を3行ではなく数文字で印刷すると便利です。

4

14 に答える 14

108

これは、目的を達成するための最小限のスタンドアロン コードです。

function timer_start {
  timer=${timer:-$SECONDS}
}

function timer_stop {
  timer_show=$(($SECONDS - $timer))
  unset timer
}

trap 'timer_start' DEBUG
PROMPT_COMMAND=timer_stop

PS1='[last: ${timer_show}s][\w]$ '
于 2009-12-07T20:43:26.497 に答える
27

あなたの返信といくつかの他のスレッドを使用して、私はあなたと共有したいこのプロンプトを書きました. 私はあなたが見ることができるスクリーンショットを撮りました:

  • 白:最後のリターンコード
  • 緑とチェック マークは成功を意味します (リターン コードは 0 でした)
  • 赤と×印はエラーを意味します (戻りコードが >0 でした)
  • (緑または赤) : 括弧内は最後のコマンド実行時刻
  • (緑または赤) : 現在の日時 (\t)
  • (ルートでない場合は緑、ルートの場合は赤): ログに記録されたユーザー名
  • (緑) : サーバー名
  • (青) : pwd ディレクトリと通常の $

カスタム プロンプト

~/.bashrc ファイルに入れるコードは次のとおりです。

function timer_now {
    date +%s%N
}

function timer_start {
    timer_start=${timer_start:-$(timer_now)}
}

function timer_stop {
    local delta_us=$((($(timer_now) - $timer_start) / 1000))
    local us=$((delta_us % 1000))
    local ms=$(((delta_us / 1000) % 1000))
    local s=$(((delta_us / 1000000) % 60))
    local m=$(((delta_us / 60000000) % 60))
    local h=$((delta_us / 3600000000))
    # Goal: always show around 3 digits of accuracy
    if ((h > 0)); then timer_show=${h}h${m}m
    elif ((m > 0)); then timer_show=${m}m${s}s
    elif ((s >= 10)); then timer_show=${s}.$((ms / 100))s
    elif ((s > 0)); then timer_show=${s}.$(printf %03d $ms)s
    elif ((ms >= 100)); then timer_show=${ms}ms
    elif ((ms > 0)); then timer_show=${ms}.$((us / 100))ms
    else timer_show=${us}us
    fi
    unset timer_start
}


set_prompt () {
    Last_Command=$? # Must come first!
    Blue='\[\e[01;34m\]'
    White='\[\e[01;37m\]'
    Red='\[\e[01;31m\]'
    Green='\[\e[01;32m\]'
    Reset='\[\e[00m\]'
    FancyX='\342\234\227'
    Checkmark='\342\234\223'


    # Add a bright white exit status for the last command
    PS1="$White\$? "
    # If it was successful, print a green check mark. Otherwise, print
    # a red X.
    if [[ $Last_Command == 0 ]]; then
        PS1+="$Green$Checkmark "
    else
        PS1+="$Red$FancyX "
    fi

    # Add the ellapsed time and current date
    timer_stop
    PS1+="($timer_show) \t "

    # If root, just print the host in red. Otherwise, print the current user
    # and host in green.
    if [[ $EUID == 0 ]]; then
        PS1+="$Red\\u$Green@\\h "
    else
        PS1+="$Green\\u@\\h "
    fi
    # Print the working directory and prompt marker in blue, and reset
    # the text color to the default.
    PS1+="$Blue\\w \\\$$Reset "
}

trap 'timer_start' DEBUG
PROMPT_COMMAND='set_prompt'
于 2016-01-15T13:52:45.747 に答える
11

別の非常に最小限のアプローチは次のとおりです。

trap 'SECONDS=0' DEBUG
export PS1='your_normal_prompt_here ($SECONDS) # '

これは、最後の単純なコマンドが開始されてからの秒数を示します。コマンドを入力せずに Enter キーを押すだけでは、カウンターはリセットされません。これは、端末で最後に何かを行ってから、端末が起動してからどれくらいの時間が経過したかを確認したい場合に便利です。Red Hat と Ubuntu では問題なく動作します。Cygwin では動作しませんでしたが、これがバグなのか、Windows で Bash を実行しようとしたときの制限なのかはわかりません。

このアプローチの考えられる欠点の 1 つは、SECONDS をリセットし続けることですが、最初のシェル呼び出しからの秒数として SECONDS を保持する必要がある場合は、SECONDS を直接使用する代わりに、PS1 カウンター用に独自の変数を作成できます。別の考えられる欠点は、「999999」などの大きな秒の値は、日 + 時間 + 分 + 秒として表示する方が適切な場合があることですが、次のような単純なフィルターを追加するのは簡単です。

seconds2days() { # convert integer seconds to Ddays,HH:MM:SS
  printf "%ddays,%02d:%02d:%02d" $(((($1/60)/60)/24)) \
  $(((($1/60)/60)%24)) $((($1/60)%60)) $(($1%60)) |
  sed 's/^1days/1day/;s/^0days,\(00:\)*//;s/^0//' ; }
trap 'SECONDS=0' DEBUG
PS1='other_prompt_stuff_here ($(seconds2days $SECONDS)) # '

これは、「999999」を「11days,13:46:39」に変換します。最後の sed は「1days」を「1day」に変更し、「0days,00:」などの先頭の空の値を切り捨てます。好みに合わせて調整してください。

于 2010-04-28T18:51:09.553 に答える
10

この zsh 借用フックを bash に利用できます: http://www.twistedmatrix.com/users/glyph/preexec.bash.txt

このフックで実行されるタイミング (Mac OS X): Growl を使用して長時間実行されるシェル コマンドを監視する

于 2009-12-07T20:50:30.103 に答える
8

長期にわたる仕事を始める前に他の答えを設定しておらず、仕事にかかった時間を知りたいだけの場合は、簡単なことを行うことができます

$ HISTTIMEFORMAT="%s " history 2

そしてそれは次のようなもので返信します

  654  1278611022 gvn up
  655  1278611714 HISTTIMEFORMAT="%s " history 2

次に、2つのタイムスタンプを視覚的に差し引くことができます(シェルビルトインの履歴コマンドの出力をキャプチャする方法を知っている人はいますか?)

于 2010-07-08T18:00:52.313 に答える
6

私は Ville Laurikari からの回答を取得し、timeコマンドを使用してそれを改善し、1 秒未満の精度を表示しました。

function timer_now {
  date +%s%N
}

function timer_start {
  timer_start=${timer_start:-$(timer_now)}
}

function timer_stop {
  local delta_us=$((($(timer_now) - $timer_start) / 1000))
  local us=$((delta_us % 1000))
  local ms=$(((delta_us / 1000) % 1000))
  local s=$(((delta_us / 1000000) % 60))
  local m=$(((delta_us / 60000000) % 60))
  local h=$((delta_us / 3600000000))
  # Goal: always show around 3 digits of accuracy
  if ((h > 0)); then timer_show=${h}h${m}m
  elif ((m > 0)); then timer_show=${m}m${s}s
  elif ((s >= 10)); then timer_show=${s}.$((ms / 100))s
  elif ((s > 0)); then timer_show=${s}.$(printf %03d $ms)s
  elif ((ms >= 100)); then timer_show=${ms}ms
  elif ((ms > 0)); then timer_show=${ms}.$((us / 100))ms
  else timer_show=${us}us
  fi
  unset timer_start
}

trap 'timer_start' DEBUG
PROMPT_COMMAND=timer_stop

PS1='[last: ${timer_show}][\w]$ '

もちろん、これにはプロセスを開始する必要があるため、効率は低下しますが、それでも気付かないほど十分に高速です。

于 2015-07-29T08:19:35.093 に答える
0

\t を PS1 に入れるとうまくいきますか?

経過時間はわかりませんが、必要に応じて時間を差し引くのは簡単です。

$ export PS1='[\t] [\w]\$ '
[14:22:30] [/bin]$ sleep 10
[14:22:42] [/bin]$

OPのコメントに従って、彼はすでに \t を使用しています。bash の代わりに tcsh を使用できる場合は、時間変数を設定できます。

/bin 1 > set time = 0
/bin 2 > sleep 10
0.015u 0.046s 0:10.09 0.4%      0+0k 0+0io 2570pf+0w
/bin 3 >

印刷の形式を変更して見栄えを良くすることができます (tcsh の man ページを参照してください)。

/bin 4 > set time = ( 0 "last: %E" )
/bin 5 > sleep 10
last: 0:10.09
/bin 6 >

私はbashの同様の機能を知りません

于 2009-12-07T20:23:16.240 に答える