# Synchronize history between bash sessions | |
# | |
# Make history from other terminals available to the current one. However, | |
# don't mix all histories together - make sure that *all* commands from the | |
# current session are on top of its history, so that pressing up arrow will | |
# give you most recent command from this session, not from any session. | |
# | |
# Since history is saved on each prompt, this additionally protects it from | |
# terminal crashes. | |
# keep unlimited shell history because it's very useful | |
export HISTFILESIZE=-1 | |
export HISTSIZE=-1 | |
shopt -s histappend # don't overwrite history file after each session | |
# on every prompt, save new history to dedicated file and recreate full history | |
# by reading all files, always keeping history from current session on top. | |
update_history () { | |
history -a ${HISTFILE}.$$ | |
history -c | |
history -r # load common history file | |
# load histories of other sessions | |
for f in `ls ${HISTFILE}.[0-9]* 2>/dev/null | grep -v "${HISTFILE}.$$\$"`; do | |
history -r $f | |
done | |
history -r "${HISTFILE}.$$" # load current session history | |
} | |
if [[ "$PROMPT_COMMAND" != *update_history* ]]; then | |
export PROMPT_COMMAND="update_history; $PROMPT_COMMAND" | |
fi | |
# merge session history into main history file on bash exit | |
merge_session_history () { | |
if [ -e ${HISTFILE}.$$ ]; then | |
cat ${HISTFILE}.$$ >> $HISTFILE | |
\rm ${HISTFILE}.$$ | |
fi | |
} | |
trap merge_session_history EXIT | |
# detect leftover files from crashed sessions and merge them back | |
active_shells=$(pgrep `ps -p $$ -o comm=`) | |
grep_pattern=`for pid in $active_shells; do echo -n "-e \.${pid}\$ "; done` | |
orphaned_files=`ls $HISTFILE.[0-9]* 2>/dev/null | grep -v $grep_pattern` | |
if [ -n "$orphaned_files" ]; then | |
echo Merging orphaned history files: | |
for f in $orphaned_files; do | |
echo " `basename $f`" | |
cat $f >> $HISTFILE | |
\rm $f | |
done | |
echo "done." | |
fi | |
@dkadioglu save and source it in your shell configuration file (usually ~/.bashrc
on Linux, ~/.bash_profile
on Mac) - like this:
source sync-history.sh
Let me know if you need more detailed instructions.
Thank you very much, works so far. One thing though: It seems, that the deletion of entries (history -d offset) is not possible anymore. At least for me, whichever item I delete, it still appears in the history. I tried to find a solution for that, without success so far. Do you have any idea?
@dkadioglu save and source it in your shell configuration file (usually
~/.bashrc
on Linux,~/.bash_profile
on Mac) - like this:source sync-history.sh
Let me know if you need more detailed instructions.
hi there i stumbled on this, and just wanted to mention that instead of using source sync-history.sh
there is a safer way to do this :
[[ -r /path/to/file.sh ]] && . /path/to/file.sh
explanation:
-
[[ -r checks fi the file that follows is readable and returns True if so
-
&& executes only if the command before returns True (or exit status 0 = success)
-
. is somewhat shorthad for source (note there is a spacebehind the '.' so '. '
result : tests is if the file exists and is readable before sourcing it.
you can combine it with:
FILE="nohup.out" ; [[ -r $FILE ]] && . $FILE ; [[ ! -e $FILE ]] && echo "! Waring $FILE not found "
wich will give you a warning if you somhow in the future accidently rename or move the file.
if you have your bash rc split up in multiple files (like i have to create some order in the chaos) you can use:
for conf in $(ls /opt/local/scripts/rc/bash/[3-9]??_*) ; do
printf "Loading: $(basename $conf)"
[[ -r "${conf}" ]] && source "${conf}"
printf '\x1b[40G\x1b[32mDONE\x1b[0m\n'
done
wich will in this case find all the files that start with a digit from 3-9 (my dir contents look like :bash 000_bashrc.conf 100_includes.conf 201_opts.conf 221_binds.conf ... 701_exports.conf hoefkens.bash_history ...
an the loop is called from within includes (wich so the 000 and 1* , 2* dont need to get loaded
and source them one by one printing a success message to stdout
starting a new tty session thus looks like:
This script sounds very interesting. But what am I supposed to do with the script? What do I have to configure how to use this?
Thanks