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

Mr *_*ooz 60 bash time prompt

有没有办法在Bash提示符中嵌入最后一个命令的已用时间?我希望有一些看起来像这样的东西:

[last: 0s][/my/dir]$ sleep 10
[last: 10s][/my/dir]$
Run Code Online (Sandbox Code Playgroud)

背景

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

自动time每一个交互式命令并将时序信息打印成几个字符而不是三行,这将是很好的.

Vil*_*ari 97

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

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]$ '
Run Code Online (Sandbox Code Playgroud)

  • 在第五个系统上实现这个并且在过去两年中使用了数万次,我想再次感谢你.它彻底改变了我的生活;-) (9认同)
  • +1你刚刚彻底改变了我的生活. (5认同)
  • 真棒.我希望时间仅显示为"慢"命令,我想要一个*铃*,所以我会自动提醒完成一个慢命令.所以:`PS1 ='$([$ timer_show -gt 10] && echo -e"\ a [$ {timer_show} s]")[\ w] $'` (3认同)
  • 这是一个丑陋的黑客.像`(date)`这样的命令行不会触发任何东西.命令行如`true | false`触发它两次(管道的每个部分一次).总而言之,它并不是我们真正需要的.bash缺乏这个功能,期间. (2认同)

Nic*_*ery 21

使用你的回复和其他一些线程,我写了这个提示,我想与你分享.我带了一个截图,你可以看到:

  • 白色:最后返回代码
  • 绿色和刻度标记表示成功(返回代码为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'
Run Code Online (Sandbox Code Playgroud)

  • Wowwweee!这是有史以来最好的事情! (3认同)
  • @NicolasThery对我来说,我必须`brew install coreutils`并将`date +%s%N`替换为`/ usr/local/opt/coreutils/libexec/gnubin/date +%s%N`以使其工作macOS Sierra. (2认同)
  • 请注意,这种使用“FancyX”和“Checkmark”的方式会破坏多行(症状与此处相同https://unix.stackexchange.com/questions/105958/terminal-prompt-not-wrapping- Correctly)。简单的解决方法是转义符号的三个部分中的两个:例如`\[\342\234\]\227`,如下所示。 (2认同)

wil*_*dye 11

另一个非常小的方法是:

trap 'SECONDS=0' DEBUG
export PS1='your_normal_prompt_here ($SECONDS) # '
Run Code Online (Sandbox Code Playgroud)

这显示自上次简单命令启动以来的秒数.计数器不复位,如果你只是按下回车键,而无需输入命令 - 这是很方便的,当你只是想看到的终端已经多久了,因为你最后做的任何事情.它适用于Red Hat和Ubuntu.它在Cygwin下对我不起作用,但我不确定这是一个bug还是仅仅是试图在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)) # '
Run Code Online (Sandbox Code Playgroud)

这将"999999"翻译成"11days,13:46:39".最后的sed将"1days"更改为"1day",并修剪空的前导值,例如"0days,00:".调整味道.


mik*_*iku 10

你可以利用这个zsh-borrowed钩子进行bash:http://www.twistedmatrix.com/users/glyph/preexec.bash.txt

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


小智 6

如果你在开始长期工作之前没有设置任何其他答案,而你只想知道工作需要多长时间,那么你可以做到这一点

$ HISTTIMEFORMAT="%s " history 2
Run Code Online (Sandbox Code Playgroud)

它会回复类似的东西

  654  1278611022 gvn up
  655  1278611714 HISTTIMEFORMAT="%s " history 2
Run Code Online (Sandbox Code Playgroud)

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

  • 你是什​​么意思,“如何捕获输出”?你可以直接使用管道,使用命令替换,`cut`,`grep`,`awk`,`perl`,`sed`... [Technologic](http://www.youtube.com) /watch?v=UoPplpBPQxQ)。 (2认同)

Tho*_*mas 5

我从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]$ '
Run Code Online (Sandbox Code Playgroud)

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