When did I run that command? Update your Bash prompt with the command start time
redandblack.io
redandblack.io
See https://github.com/naggie/dotfiles/blob/master/home/.functio...
One of my most useful changes is a script that garbage-collects my history file: deduplication, removal of sensitive + trivial commands. In combination with a FZF based history search that's shared between all shells, I effectively have a super-quick database of every command without any noise. See https://github.com/naggie/dotfiles/blob/master/scripts/clean... -- added via bash/zsh hooks.
In addition, I can do it in such a way that the most recent invocation is deleted last. I can also use regexes.
See https://github.com/naggie/dotfiles/blob/master/scripts/clean... for more reasoning.
There is also a similar builtin feature [1] of ZSH. For example, you can put this in your .zshrc:
REPORTTIME=10
It instructs ZSH to report the time elapsed since the command was invoked (if it is above this threshold, 10 seconds in this case).
However, it just takes the CPU time into account. When using something like `sleep`, it won't trigger. There is a plugin [2] that covers this use case aswell.[1]: https://nuclearsquid.com/writings/reporttime-in-zsh/ [2]: https://github.com/popstas/zsh-command-time
I don't mean that it would show the time when the prompt was written to the terminal. That's easy.
I mean that it would show the time when the command entered at it was executed. Those two times can be very different.
This little hack updates your Bash prompt with the current time when you execute a command.
As someone who spends many hours every day in the terminal, it's improved my life. Maybe it can help you too.
I know not everyone is on the zsh train, but it might be able to be ported to bash (it's just pre-hooks and some sqlite)
export HISTTIMEFORMAT="%d/%m/%y %T "
to your .bashrc and then history
will show the date and time before each command that was run.With an updating prompt, you can see when a command ran without having to type 'history'.
And adding a date/time stamp to history is very useful when you need to go back further - hours, days or months.
My preference is just for a date in the history, rather than date and time. I find that when I'm searching history, date is usually granular enough for me, so I can omit the time and save a little bit of screen real estate.
1) It made the history command run much, much slower (I have HISTSIZE=100000)
2) Dates tend to reset to a uniform but meaningless value. I think it's related to OS reboots.
When I last needed it ~2011, there was a small and simple tool called libsnoopy for that.
Emphasis on "log file" though, the "history file" is a different use case, fundamentally unfit for forensics.
## History configuration, see HISTORY in bash(1)
## builtin fc, aka fix command, for history manipulation
## fc [-e ename] [-lnr] [first] [last]
## -e or invoke editor ename; defaults to $FCEDIT
## -l or list commands
## -n or suppress entry numbers
## -r or reverse command order
## first, last selects a range of entries by numeric index
##
## fc -s [pat=rep] [cmd]
## -s or substitute all occurences of pat with rep
#
# - h() is short for history
# - r() is short for replay
# - always append to the history, don't overwrite
# - save multi-line commands in a single entry
# - insist on vim everywhere
# - don't record commands with a leading space or duplicates
# - constrain the size of the history file
# - ignore common things
# - constrain the number of history entries
# - set up nicer timestamps
alias h="history"
alias r="fc -s"
shopt -s histappend
shopt -s cmdhist
export FCEDIT=$EDITOR
export HISTCONTROL=ignoreboth
export HISTFILE=$HOME/.bash_history
export HISTFILESIZE=1048576
export HISTIGNORE='ls:ls -l:ls -latr:ps -ef:fc:h:history:clear:exit'
export HISTSIZE=8192
export HISTTIMEFORMAT='[%F %T] 'I wonder why this is not more standard. Most shells write a single global histfile to $HOME.
For Bash, in ~/.bashrc:
export PROMPT_COMMAND="myLocalHistory"
# we don't need everything within the history
alias useHistory='grep -E -v "^ls$|^ll$|^l$|^dir$|^cd |^bg$|^fg$|^qstat |^note |^mutt|^std|^clear$|^qinfo$|^gh|^qw$" | wc -l'
function myLocalHistory()
{
HISTORYLINE=`history | tail -1 | sed 's:^ *[0-9]* *::g'`
if [ `echo $HISTORYLINE | useHistory` == 1 ] ; then
((date +%F.%H-%M-%S | tr -d '\n' ; echo " $HISTORYLINE") >>.history.$USER) 2>/dev/null
fi
}
For ZSH, in ~/.zshrc: preexec () {
~/dotfiles/system-tools/helpers/local-history-add.py $1 >/dev/null
}
For Fish, in ~/.config/fish/config.fish: function fish_preexec --on-event fish_preexec
~/dotfiles/system-tools/helpers/local-history-add.py $argv &
end
The script local-history-add.py is here: https://github.com/albertz/helpers/blob/master/local-history...The Bash solution probably could also be simplified by using this script, which takes care of filtering logic and adding it to the history file, in your preferred format.
These are most of the settings in ZSH I use to enable all that.
HISTSIZE=10000000
SAVEHIST=10000000
setopt EXTENDED_HISTORY # logs the start and elapsed time
setopt INC_APPEND_HISTORY
setopt SHARE_HISTORY
setopt HIST_IGNORE_DUPS
setopt HIST_IGNORE_ALL_DUPS
setopt HIST_FIND_NO_DUPS
Apple now even recommends zsh shell over bash! =)
https://support.apple.com/en-us/HT208050 (it's the 10.15 default)Worth reading why they did that: https://thenextweb.com/dd/2019/06/04/why-does-macos-catalina...
I do this from Emacs (you can use Helm or Ivy, for example) and it's extremely convenient and effective to quickly get old commands back.
As in, the shift key's required.
if $INTERACTIVE; then
# http://superuser.com/a/175802
# show date when command was executed
preexec() {
[ -n "$COMP_LINE" ] && return # do nothing if completing
[ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
echo -ne "\033[$(( COLUMNS-15 ))C$(date +'%m%d-%H:%M:%S')\r"
}
trap 'preexec' DEBUG
fi
The `echo -ne ...` is what prints the date (month+day+time, year is assumed obvious) close to the right margin (COLUMNS-15), then prints `\r` to get back to left margin. This has pros (less space taken) and cons (shows up in copy&paste), you can surely edit the format to your liking if you prefer.I'll have to check how the OP's PS0 compares with that however, maybe it can make my snippet even simpler? edit: Ah, IIUC, PS0 seems bash 4.4+, for better or worse: https://github.com/rcaloras/bash-preexec/issues/28
If I rewrote the prompt each time I ran a command, I’d lose that record. (I suppose I could do the same trick in reverse and if I care to know how long a command will take, I could run it and hit enter a few times to queue up an empty command to create the same timestamp effect after the fact).
https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash....
It's executed just before the PS1 prompt is printed.
A nice idea I've seen is to use PROMPT_COMMAND to print the time a command finished (and maybe an indication of its exit status) in low-contrast text at the far right of the terminal. Then that info is there if you want to look for it, but it's not distracting.
Then you could have the best of both worlds, and it would all happen without the need to remember to create fresh prompts.
PROMPT_COMMAND='echo "$(date "+%Y-%m-%d.%H:%M:%S") $(pwd) $(HISTTIMEFORMAT= history 1)" >> ~/.logs/bash/bash-history-$(date "+%Y-%m-%d").log'
I forget where I learned this. What it does is write the bash history to a log file, with the date/time, directory of the command, and the command. Occasionally it has helped me find where a file is that I was working on :)
This is printing the time you pressed Enter (the time the command started), which is harder and less common, since that's not when the prompt is printed.
Instead, this seems to work:
TRAPDEBUG() {
case "$WIDGET" in
zle-line-finish)
zle reset-prompt
;;
*)
;;
esac
}
(I don't know if further cases will be required.)This updates the prompt after "enter" is pressed, but before the command is executed.
"\C-xj": "\C-e\C-u # `pwd`\e\C-e\C-a\C-y\C-j"
Whenever you want a command saved with the launch directory, instead of Enter, press "CTRL-x j"
time my_cmd".,d": "\C-adate; \C-e; date\n"
Whenever I want a command dated like in your suggestion, instead of pressing Enter to execute the command, I press the key-sequence ".,d" and the command gets wrapped in 'date' calls.
Mine works but is hacky, it would be nice to have a more neatly packaged solution.
https://git.sr.ht/~sircmpwn/dotfiles/tree/master/bin/prompt....
I suspect that we'll be seeing a lot more of these kinds of things, coming out of this "house arrest" situation.
I’ve been tempted to add time logging by something similar to PS1=“$(date)\r$PS1” Because I don’t really care about the execution time of current commands but might care historically.
The thing is that the prompt might sit there for minutes or hours before you use it to run a command, so that timestamp doesn't reliably serve as an accurate record of when a command was run.
That's the problem which my approach addresses by updating the timestamp when a command is run.
If I did, It’s also possible to get amount of time a command required to complete. Based on that execution time in conjunction with the timestamp of the next print of PS1 it would be easy to deduce the time when a line was actually executed, rather than when typing of the line began, but at that point I’d probably just record my screen to track any harder to determine behaviours.
Is it the same or something different?