perfect bash history

xaxazak

New Member
Joined
Nov 3, 2023
Messages
2
Reaction score
1
Credits
38
I've been trying to config my perfect bash history setup, but there's always something not working.
  • scroll through commands from current bash session in chronological order, then scroll through commands from all other sessions, whether open or closed, in chronological order of the commands.
  • don't show duplicates (not a big deal if it appears twice, once for current session once for everything else).
  • bonus 1: some indicator (eg text color) that scrolling has switched from current session history to all other sessions.
  • bonus 2: search (ctrl-R) should search through all commands from all sessions (current, open, or closed).
Is it possible to achieve this?
Thanks.
 


By default the "history" command already shows the command history in chronological order.

If you don't want duplicates to show up in a 'history' list you add this to your .bashrc file.

export HISTCONTROL=ignoredups

If you want to do this in real time, you can just use...

history | uniq

I'm not exactly sure what you mean by other sessions. If you mean two terminal consoles at the same time,
you can't do this in real time. The history in each console will be different.

If you mean other users history, you would have to either be root, or know their passwd.

Then you have two choices.... su - to that user and run the history command.
Or you can remain root, and cat /home/user/.bash_history

The only way I know of the achieve the "bonus 2"
Would be with a shell script that does what I did in the previous example ( cat the users .bash_history file )
except loop through all the users in the /home directory.

Keep in mind, user can edit their own history files, ( even erase them entirely ) if they know how.
So this isn't 100% percent foolproof for auditing purposes.

Also by default, history doesn't show the time that a specific command was ran, it only shows the order.
You can add the time a command was ran by doing this.

You can add this to to your .bashrc file ( you have to do this for every user )

export HISTTIMEFORMAT="%F %r "
 
This isn't really part of your requirements, but if you are doing this for security/auditing reasons, you
can install and enable auditd, which was made specifically for this purpose. There is quite a bit
of logging overhead, when this is running.

The other option, is to install something like "inotify-tools" which is available for most distros.

Then have a shell script like this running.

#!/bin/bash
USER=username # Replace 'username' with the target user's username
HISTORY_FILE="/home/$USER/.bash_history"
BACKUP_DIR="/var/log/user_history_backups" # Create this directory if it doesn't exist
inotifywait -m -e modify,delete,create -r --format %f $HISTORY_FILE | while read FILE
do
cp $HISTORY_FILE $BACKUP_DIR/"$USER"history$(date +"%Y%m%d_%H%M%S").log
done

You would probably want that running as a systemd process, so that it runs automatically in the background when the computer is running.

 
Last edited:
By default the "history" command already shows the command history in chronological order.
I'm not exactly sure what you mean by other sessions. If you mean two terminal consoles at the same time,
you can't do this in real time. The history in each console will be different.
Yeah, other "bash sessions" / terminals. I'll use terminals if that's easier.

By default, terminals scroll through their own history, then once that's exhausted they read through "~/.bash_history". But that history doesn't contain other open/live terminals. I'm guessing the current terminal's history is stored in memory in the bash session somehow. Is there a name for this local current-terminal-history I can use to disambiguate vs the global shared "~/.bash_history" history? (I'll use local-history vs global-history).

If I use "PROMPT_COMMAND=history -a; history -c; history -r;" then I get to scroll through other open/live terminals' commands, but local-history is mixed with global-history.

Using just "history -a" allows terminals opened after a command to see that command in global-history even if the terminal that launched that command is still live.

IIUC, using "history -a; history -n" should be exactly what I want (from "history --help"), but it doesn't seem to work as described. "history -a" only writes 1 entry (even direct from the command line), and "history -n" only loads 1 entry, which is the one written by "history -a". Am I misunderstanding something or is the help description inaccurate?

I can just launch a new terminal (or purge an existing terminal using a custom script, shuffling the local-history into global-history) any time I want to scroll through all history. But this is time consuming and annoying (if done often), and it's what I'm trying to avoid.

This feels like a history daemon (rather than only a history file) would solve my problems except writing it would be a major project and I don't think I have the time at the moment.

Then have a shell script like this running.
...
I'm not doing it for auditing or anything.

Basically, I usually have lots of terminals running. A few development ones, some one-shot ones for things like pacman, some for queueing music, etc. "history -a" (mostly) avoids losing commands.
 

Members online


Top