如何将最后一个命令的挂起时间放入 Bash 提示符中?

发布于 2024-08-14 01:21:28 字数 402 浏览 12 评论 0原文

有没有办法将最后一个命令的运行时间嵌入到 Bash 提示符中?我希望看到这样的东西:

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

背景

我经常进行长时间的数据处理工作,知道它们花了多长时间很有用,这样我就可以估计未来需要多长时间工作机会。对于非常常规的任务,我会继续使用适当的日志记录技术严格记录这些信息。对于不太正式的任务,我只需在命令前面加上时间

如果能自动为每个交互式命令计时,并以几个字符而不是 3 行打印计时信息,那就太好了。

Is there a way to embed the last command's elapsed wall time in a Bash prompt? I'm hoping for something that would look like this:

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

Background

I often run long data-crunching jobs and it's useful to know how long they've taken so I can estimate how long it will take for future jobs. For very regular tasks, I go ahead and record this information rigorously using appropriate logging techniques. For less-formal tasks, I'll just prepend the command with time.

It would be nice to automatically time every single interactive command and have the timing information printed in a few characters rather than 3 lines.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

℉服软 2024-08-21 01:21:28

这是实现您想要的功能的最小独立代码:

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]$ '

This is minimal stand-alone code to achieve what you want:

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]$ '
饮惑 2024-08-21 01:21:28

根据您的回复和其他一些帖子,我写了这个提示,我想与您分享。我拍了一张屏幕截图,您可以看到:

  • 白色:最后一个返回代码
  • 绿色和勾号表示成功(返回代码为 0)
  • 红色和十字标记表示错误(返回代码>0)
  • (绿色或红色):最后一个命令执行括号中的时间
  • (绿色或红色):当前日期时间 (\t)
  • (如果不是 root,则绿色,如果 root,则红色):记录的用户名
  • (绿色):服务器名称
  • (蓝色):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'

Using your replies and some other threads, I wrote this prompt which I want to share with you. I took a screenshot in wich you can see :

  • White : Last return code
  • Green and tick mark means success (return code was 0)
  • Red and cross mark means error (return code was >0)
  • (Green or Red) : Last command execution time in parenthesis
  • (Green or Red) : Current date time (\t)
  • (Green if not root, Red if root) : the logged username
  • (Green) : the server name
  • (Blue) : the pwd directory and the usual $

Custom prompt

Here is the code to put in your ~/.bashrc file :

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'
莫相离 2024-08-21 01:21:28

您可以将这个 zsh 借用的钩子用于 bash: http://www.twistedmatrix .com/users/glyph/preexec.bash.txt

使用此钩子完成的计时 (Mac OS X): 使用 Growl 监视长时间运行的 shell 命令

You could utilize this zsh-borrowed hook for bash: http://www.twistedmatrix.com/users/glyph/preexec.bash.txt

Timing done with this hook (Mac OS X): Use Growl to monitor long-running shell commands

九命猫 2024-08-21 01:21:28

另一个非常简单的方法是:

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

这显示自上一个简单命令启动以来的秒数。如果您只是按 Enter 键而不输入命令,则计数器不会重置 - 当您只想查看自上次在终端中执行任何操作以来终端已启动多长时间时,这会很方便。它在 Red Hat 和 Ubuntu 中对我来说工作得很好。它在 Cygwin 下对我不起作用,但我不确定这是一个错误还是只是尝试在 Windows 下运行 Bash 的限制。

这种方法的一个可能的缺点是您不断重置 SECONDS,但如果您确实需要将 SECONDS 保留为自初始 shell 调用以来的秒数,您可以为 PS1 计数器创建自己的变量,而不是直接使用 SECONDS。另一个可能的缺点是,诸如“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”转换为“11天,13: 46:39”。最后的 sed 将“1days”更改为“1day”,并修剪掉空的前导值,例如“0days,00:”。调整口味。

Another very minimal approach is:

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

This shows the number of seconds since the last simple command was started. The counter is not reset if you simply hit Enter without entering a command -- which can be handy when you just want to see how long the terminal has been up since you last did anything in it. It works fine for me in Red Hat and Ubuntu. It did NOT work for me under Cygwin, but I'm not sure if that's a bug or just a limitation of trying to run Bash under Windows.

One possible drawback to this approach is that you keep resetting SECONDS, but if you truly need to preserve SECONDS as the number of seconds since initial shell invocation, you can create your own variable for the PS1 counter instead of using SECONDS directly. Another possible drawback is that a large seconds value such as "999999" might be be better displayed as days+hours+minutes+seconds, but it's easy to add a simple filter such as:

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)) # '

This translates "999999" into "11days,13:46:39". The sed at the end changes "1days" to "1day", and trims off empty leading values such as "0days,00:". Adjust to taste.

熊抱啵儿 2024-08-21 01:21:28

如果您在开始长时间运行的工作之前没有设置任何其他答案,并且您只想知道该工作花了多长时间,您可以做简单的事情

$ HISTTIMEFORMAT="%s " history 2

,它会回复类似的内容

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

,然后您可以直观地减去两个时间戳(有人知道如何捕获 shell 内置历史命令的输出吗?)

If you hadn't set up any of the other answers before you kicked off your long-running job and you just want to know how long the job took, you can do the simple

$ HISTTIMEFORMAT="%s " history 2

and it will reply with something like

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

and you can then just visually subtract the two timestamps (anybody know how to capture the output of the shell builtin history command?)

尛丟丟 2024-08-21 01:21:28

我从 Ville Laurikari 那里得到了答案,并使用 time 命令改进了它,以显示亚秒级精度:

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]$ '

当然,这需要启动一个进程,因此效率较低,但仍然足够快,您不会没注意到。

I took the answer from Ville Laurikari and improved it using the time command to show sub-second accuracy:

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]$ '

Of course this requires a process to be started, so it's less efficient, but still fast enough that you wouldn't notice.

温柔女人霸气范 2024-08-21 01:21:28

这是我对 Thomas

使用 date +%s%3N 获取毫秒作为基本单位的看法,
简化以下代码(减少零)

function t_now {
    date +%s%3N
}

function t_start {
    t_start=${t_start:-$(t_now)}
}

function t_stop {
    local d_ms=$(($(t_now) - $t_start))
    local d_s=$((d_ms / 1000))
    local ms=$((d_ms % 1000))
    local s=$((d_s % 60))
    local m=$(((d_s / 60) % 60))
    local h=$((d_s / 3600))
    if ((h > 0)); then t_show=${h}h${m}m
    elif ((m > 0)); then t_show=${m}m${s}s
    elif ((s >= 10)); then t_show=${s}.$((ms / 100))s
    elif ((s > 0)); then t_show=${s}.$((ms / 10))s
    else t_show=${ms}ms
    fi
    unset t_start
}
set_prompt () {
t_stop
}

trap 't_start' DEBUG
PROMPT_COMMAND='set_prompt' 

然后将 $t_show 添加到您的 PS1

Here's my take on Thomas'

uses date +%s%3N to get milliseconds as base unit,
simplified following code (less zeros)

function t_now {
    date +%s%3N
}

function t_start {
    t_start=${t_start:-$(t_now)}
}

function t_stop {
    local d_ms=$(($(t_now) - $t_start))
    local d_s=$((d_ms / 1000))
    local ms=$((d_ms % 1000))
    local s=$((d_s % 60))
    local m=$(((d_s / 60) % 60))
    local h=$((d_s / 3600))
    if ((h > 0)); then t_show=${h}h${m}m
    elif ((m > 0)); then t_show=${m}m${s}s
    elif ((s >= 10)); then t_show=${s}.$((ms / 100))s
    elif ((s > 0)); then t_show=${s}.$((ms / 10))s
    else t_show=${ms}ms
    fi
    unset t_start
}
set_prompt () {
t_stop
}

trap 't_start' DEBUG
PROMPT_COMMAND='set_prompt' 

Then add $t_show to your PS1

地狱即天堂 2024-08-21 01:21:28

我发现每次调用 $PROMPT_COMMAND 时都会运行 trap ... DEBUG ,重置计时器,因此总是返回 0。

但是,我发现 history 记录时间,我利用这些来得到答案:

HISTTIMEFORMAT='%s '
PROMPT_COMMAND="
  START=\$(history 1 | cut -f5 -d' ');
  NOW=\$(date +%s);
  ELAPSED=\$[NOW-START];
  $PROMPT_COMMAND"
PS1="\$ELAPSED $PS1"

但这并不完美:

  • 如果 history 没有注册命令(例如重复或忽略的命令),则开始时间将为错误的。
  • 多行命令无法从历史记录中正确提取日期。

I found that trap ... DEBUG was running every time $PROMPT_COMMAND was called, resetting the timer, and therefore always returning 0.

However, I found that history records times, and I tapped into these to get my answer:

HISTTIMEFORMAT='%s '
PROMPT_COMMAND="
  START=\$(history 1 | cut -f5 -d' ');
  NOW=\$(date +%s);
  ELAPSED=\$[NOW-START];
  $PROMPT_COMMAND"
PS1="\$ELAPSED $PS1"

It's not perfect though:

  • If history doesn't register the command (e.g. repeated or ignored commands), the start time will be wrong.
  • Multi-line commands don't get the date extracted properly from history.
望她远 2024-08-21 01:21:28

zsh 的翻译版本。

附加到您的 ~/.zshrc 文件

function preexec() {
  timer=$(date +%s%3N)
}

function precmd() {
  if [ $timer ]; then
    local now=$(date +%s%3N)
    local d_ms=$(($now-$timer))
    local d_s=$((d_ms / 1000))
    local ms=$((d_ms % 1000))
    local s=$((d_s % 60))
    local m=$(((d_s / 60) % 60))
    local h=$((d_s / 3600))
    if ((h > 0)); then elapsed=${h}h${m}m
    elif ((m > 0)); then elapsed=${m}m${s}s
    elif ((s >= 10)); then elapsed=${s}.$((ms / 100))s
    elif ((s > 0)); then elapsed=${s}.$((ms / 10))s
    else elapsed=${ms}ms
    fi

    export RPROMPT="%F{cyan}${elapsed} %{$reset_color%}"
    unset timer
  fi
}

Translated version for zsh.

Append to your ~/.zshrc file

function preexec() {
  timer=$(date +%s%3N)
}

function precmd() {
  if [ $timer ]; then
    local now=$(date +%s%3N)
    local d_ms=$(($now-$timer))
    local d_s=$((d_ms / 1000))
    local ms=$((d_ms % 1000))
    local s=$((d_s % 60))
    local m=$(((d_s / 60) % 60))
    local h=$((d_s / 3600))
    if ((h > 0)); then elapsed=${h}h${m}m
    elif ((m > 0)); then elapsed=${m}m${s}s
    elif ((s >= 10)); then elapsed=${s}.$((ms / 100))s
    elif ((s > 0)); then elapsed=${s}.$((ms / 10))s
    else elapsed=${ms}ms
    fi

    export RPROMPT="%F{cyan}${elapsed} %{$reset_color%}"
    unset timer
  fi
}
抚你发端 2024-08-21 01:21:28

bash 4.x 及更高版本的另一种方法是将 coprocPS0PS1 一起使用,如下所示:

cmd_timer()
{
    echo $(( SECONDS - $(head -n1 <&"${CMD_TIMER[0]}") ))
}

coproc CMD_TIMER ( while read; do echo $SECONDS; done )
echo '' >&"${CMD_TIMER[1]}" # For value to be ready on first PS1 expansion
export PS0="\$(echo '' >&${CMD_TIMER[1]})"
export PS1="[ \$(cmd_timer) ] \$"

这是一个 .bashrc 准备好的片段。
它对于使用 undistract-me 的每个人来说特别有用,它会覆盖 trap DEBUG 出于其自身目的。

Another approach for bash 4.x and above would be to use coproc with PS0 and PS1 like below:

cmd_timer()
{
    echo $(( SECONDS - $(head -n1 <&"${CMD_TIMER[0]}") ))
}

coproc CMD_TIMER ( while read; do echo $SECONDS; done )
echo '' >&"${CMD_TIMER[1]}" # For value to be ready on first PS1 expansion
export PS0="\$(echo '' >&${CMD_TIMER[1]})"
export PS1="[ \$(cmd_timer) ] \$"

This is a .bashrc ready snippet.
It is especially useful for everyone that uses undistract-me which overwrites trap DEBUG for its own purposes.

看轻我的陪伴 2024-08-21 01:21:28

如果有人只是想看看执行时间
将此行添加到 bash_profile

trap 'printf "t=%s\n" $(date +%T.%3N)' DEBUG

If somone just wants to see the time of execution,
add this line to bash_profile

trap 'printf "t=%s\n" $(date +%T.%3N)' DEBUG
无人接听 2024-08-21 01:21:28

zsh spaceship 提示符启发的分时、分、秒版本,基于 Ville的回答这次转换函数< /a> 佩雷亚尔。

我还添加了一个阈值变量,以便计时器仅显示长时间运行的命令。

提示输出

time_threshold=5;

function convert_secs {
    ((h=${1}/3600))
    ((m=(${1}%3600)/60))
    ((s=${1}%60))
    if [ $h -gt 0 ]; then printf "${h}h "; fi
    if [ $h -gt 0 ] || [ $m -gt 0 ]; then printf "${m}m "; fi
    if [ $s -gt 0 ]; then printf "${s}s "; fi
}

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

function timer_stop {
    timer_time=$(($SECONDS - $timer))
    
    if [ ! -z $timer_time ] && [ $timer_time -ge ${time_threshold} ]; then
        timer_show="took $(convert_secs $timer_time)"
    else
        timer_show=""
    fi

    unset timer
}

trap 'timer_start' DEBUG
PROMPT_COMMAND=timer_stop

PS1='\n\w ${timer_show}\n\\$ '

对于我的屏幕截图中的彩色输出:

bold=$(tput bold)
reset=$(tput sgr0)
yellow=$(tput setaf 3)
cyan=$(tput setaf 6)

PS1='\n${bold}${cyan}\w ${yellow}${timer_show}${reset}\n\\$ '

A version with split hours, minutes and seconds inspired by the zsh spaceship prompt, based on Ville's answer and this time conversion function by perreal.

I also added a threshold variable so that the timer only displays for long running commands.

prompt output

time_threshold=5;

function convert_secs {
    ((h=${1}/3600))
    ((m=(${1}%3600)/60))
    ((s=${1}%60))
    if [ $h -gt 0 ]; then printf "${h}h "; fi
    if [ $h -gt 0 ] || [ $m -gt 0 ]; then printf "${m}m "; fi
    if [ $s -gt 0 ]; then printf "${s}s "; fi
}

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

function timer_stop {
    timer_time=$(($SECONDS - $timer))
    
    if [ ! -z $timer_time ] && [ $timer_time -ge ${time_threshold} ]; then
        timer_show="took $(convert_secs $timer_time)"
    else
        timer_show=""
    fi

    unset timer
}

trap 'timer_start' DEBUG
PROMPT_COMMAND=timer_stop

PS1='\n\w ${timer_show}\n\\$ '

For the coloured output in my screenshot:

bold=$(tput bold)
reset=$(tput sgr0)
yellow=$(tput setaf 3)
cyan=$(tput setaf 6)

PS1='\n${bold}${cyan}\w ${yellow}${timer_show}${reset}\n\\$ '
两人的回忆 2024-08-21 01:21:28

在 PS1 中添加 \t 对你有用吗?

它不会给出经过的时间,但在必要时应该很容易减去时间。

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

根据OP的评论,他已经在使用\t。
如果您可以使用 tcsh 而不是 bash,则可以设置时间变量。

/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 手册页)。

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

我不知道 bash 中有类似的功能

Will putting a \t in PS1 work for you?

It does not give the elapsed time but it should be easy enough to subtract the times when necessary.

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

Following the OP's comment that he is already using \t.
If you can use tcsh instead of bash, you can set the time variable.

/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 >

You can change the format of the printing to be less ugly (se the tcsh man page).

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

I do not know of a similar facility in bash

千鲤 2024-08-21 01:21:28

这是我的版本

  • 使用日期来格式化时间,仅计算天数
  • 设置终端标题
  • 在 PS1 中使用 \$ for user $ + root #
  • 显示返回代码/退出代码
  • 使用 date -u 禁用 DST
  • 使用隐藏名称,如 _foo
_x_dt_min=1 # minimum running time to show delta T
function _x_before {
    _x_t1=${_x_t1:-$(date -u '+%s.%N')} # float seconds
}
function _x_after {
    _x_rc=$? # return code
    _x_dt=$(echo $(date -u '+%s.%N') $_x_t1 | awk '{printf "%f", $1 - $2}')
    unset _x_t1
    #_x_dt=$(echo $_x_dt | awk '{printf "%f", $1 + 86400 * 1001}') # test
    # only show dT for long-running commands
    # ${f%.*} = int(floor(f))
    (( ${_x_dt%.*} >= $_x_dt_min )) && {
        _x_dt_d=$((${_x_dt%.*} / 86400))
        _x_dt_s='' # init delta T string
        (( $_x_dt_d > 0 )) && \
            _x_dt_s="${_x_dt_s}${_x_dt_d} days + "
        # format time
        # %4N = four digits of nsec
        _x_dt_s="${_x_dt_s}$(date -u -d0+${_x_dt}sec '+%T.%4N')"
        PS1='rc = ${_x_rc}\ndT = ${_x_dt_s}\n\$ '
    } || {
        PS1='rc = ${_x_rc}\n\$ '
    }
    # set terminal title to terminal number
    printf "\033]0;%s\007" $(tty | sed 's|^/dev/\(pts/\)\?||')
}
trap '_x_before' DEBUG
PROMPT_COMMAND='_x_after'
PS1='\$ '

示例输出:

$ sleep 0.5
rc = 0
$ sleep 1
rc = 0
dT = 00:00:01.0040
$ sleep 1001d
rc = 0
dT = 1001 days + 00:00:00.0713
$ false
rc = 1
$ 

this is my version

  • use date to format time, only calc days
  • set terminal title
  • use \$ in PS1 for user $ + root #
  • show return code / exit code
  • use date -u to disable DST
  • use hidden names like _foo
_x_dt_min=1 # minimum running time to show delta T
function _x_before {
    _x_t1=${_x_t1:-$(date -u '+%s.%N')} # float seconds
}
function _x_after {
    _x_rc=$? # return code
    _x_dt=$(echo $(date -u '+%s.%N') $_x_t1 | awk '{printf "%f", $1 - $2}')
    unset _x_t1
    #_x_dt=$(echo $_x_dt | awk '{printf "%f", $1 + 86400 * 1001}') # test
    # only show dT for long-running commands
    # ${f%.*} = int(floor(f))
    (( ${_x_dt%.*} >= $_x_dt_min )) && {
        _x_dt_d=$((${_x_dt%.*} / 86400))
        _x_dt_s='' # init delta T string
        (( $_x_dt_d > 0 )) && \
            _x_dt_s="${_x_dt_s}${_x_dt_d} days + "
        # format time
        # %4N = four digits of nsec
        _x_dt_s="${_x_dt_s}$(date -u -d0+${_x_dt}sec '+%T.%4N')"
        PS1='rc = ${_x_rc}\ndT = ${_x_dt_s}\n\$ '
    } || {
        PS1='rc = ${_x_rc}\n\$ '
    }
    # set terminal title to terminal number
    printf "\033]0;%s\007" $(tty | sed 's|^/dev/\(pts/\)\?||')
}
trap '_x_before' DEBUG
PROMPT_COMMAND='_x_after'
PS1='\$ '

sample output:

$ sleep 0.5
rc = 0
$ sleep 1
rc = 0
dT = 00:00:01.0040
$ sleep 1001d
rc = 0
dT = 1001 days + 00:00:00.0713
$ false
rc = 1
$ 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文