Last active
October 19, 2024 08:12
-
-
Save jan-warchol/89f5a748f7e8a2c9e91c9bc1b358d3ec to your computer and use it in GitHub Desktop.
Synchronize history across bash sessions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 | |
Is there a way to record only direct inputs? Now it seems it catches all inputs, history file is full of mc's outputs like:
cd "printf '%b' '\0057home
"
Still trying to fix this to use with tmux. Now it catches all the commands sent from random apps, but later this breaks the input ending up with:
$ mc
$ ls -la
$ ls -latop
can't remove that ^ ls -la
upd: Ok, that part probably was caused by cyd01/KiTTY and fixed by changing termtype to tmux-256color
MC's internal commands has a leading space so it won't be saved in history, but it still gets saved. Fixed it by checking for leading space and exiting the function. But is there a better solution to rrecord only user inputs?
update_history () {
lastCmd=$(fc -lnr | head -n1)
# clean the spaces left by fc
lastCmdReal=${lastCmd:2}
# remove all leading spaces
lastCmdRealClean=${lastCmd##+([[:space:]])}
if [[ "$lastCmdReal" == " $lastCmdRealClean" ]]; then
return 0
fi
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@hoefkensj ambitious@nice, but could not make it work. In the end I just:
export HISTFILE=~/.bash/.bash_history