Bash history with multiple sessions
Today I spent a bit of time investigating a rather annoying buglet that seems to have shown up since Fedora 21. I'd been noticing, vaguely, that things I was sure should be in my bash history weren't there.
So far we're guessing the bug happens when you reboot with a terminal app running; it seems sometimes the active sessions don't get time to write the history out to the bash history file before they're killed. It may be related to this bug, though waiting to hear back from the systemd devs on that.
Anyway, while looking into bash's behaviour in this area, I came across a nice snippet from Bradley Kuhn, and I've taken the liberty of adopting that (it's GPL, right Bradley? :>) and tweaking it a bit:
HISTSIZE=1048576
HISTFILESIZE=1048576
LAST_HISTORY_WRITE=$SECONDS
function prompt_command {
if [ $(($SECONDS - $LAST_HISTORY_WRITE)) -gt 60 ]; then
history -a && history -c && history -r
LAST_HISTORY_WRITE=$SECONDS
fi
}
PROMPT_COMMAND="$PROMPT_COMMAND; prompt_command"
I saved this as /etc/profile.d/zz-happyassassin-history-safe.sh
. There's a /etc/profile.d/vte.sh
which overwrites any previous PROMPT_COMMAND
, so you need to make sure it's alphabetically after that, and I have a convention of including happyassassin
in the names of config files that are my own customizations, so I can conveniently identify them.
Basically, every time I run a command, if it's been more than 60 seconds since the last time this happened, it saves the current session's history to the history file (history -a
), clears the current session's history (history -c
) and reads the history back in from the file (history -r
).
This both protects against the problem where you lose commands from active sessions at shutdown, and means when you have lots of shells open at once (in tabs or windows or whatever), every 60 seconds each will pick up history from all the others - I get a bit annoyed when I have six terminals open and I realize I need something from the history of a different terminal but I can't remember which one...
You can tweak the frequency by changing 60
to something else - Bradley's snippet had 300
so it'd happen every 5 minutes, for testing I set it to 5
. You could even drop the timer entirely and have it happen every time you run a command, for maximum safety (and to keep the order of the commands as accurate as possible, I guess). On an SSD at least, this happens so fast you don't notice it - it might take a bit longer if you have the 11MiB history file discussed in the initial thread, so tweak to your desires.
I've been running this for a whole twenty minutes so far, so I'll update this post if it turns out to cause terrible casualties or anything, but just thought I'd note it quickly first :)
EDIT: I've been using this since and generally like it, though it does have drawbacks. Reading the history from other consoles back into the current console regularly changes the order of the history - you can't be sure that pressing 'up' three times will give you the third-last command from that console. Which is sometimes annoying. But overall, I'm happy with it.
Comments
I'll run anything made by Oracle the same day I buy an iPhone, thanks.