Configuration Information [Automatically generated, do not change]: Machine: i486 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='i486' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i486-pc-linux-gnu' -DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I../bash -I../bash/include -I../bash/lib -g -O2 uname output: Linux roland 2.6.18.5roland2 #1 Mon Mar 19 19:11:42 CET 2007 i686 GNU/Linux Machine Type: i486-pc-linux-gnu
Bash Version: 3.1 Patch Level: 17 Release Status: release Description: bash overwrites most history entries, if several instances run simultanously Repeat-By: Consider you have KDE with several konsole windows and several bash sessions running, you shut down KDE and want KDE session restoring after next time booting. With default configuration all bash instances try to write (almost) simultanously to the same ~/.bash_history, the last closing instance overwrites the new history entries of ALL OTHER instances which are SILENTLY LOST. If for your debugging and fixing more details of my configuration would be helpful, please mail me. Fix: I tried some workarounds, this 2 may be useful for others: Workaround 1: usage of $PROMPT_COMMAND --------------------------------------- Searching Internet I found this suggestion for PROMPT_COMMAND (sorry, cannot remember URL), combined with HISTTIMEFORMAT and in /etc/fstab adding "commit=30" to ext3 mount options, it is my currently used workaround: # /etc/bash.bashrc # ---------------- export HISTTIMEFORMAT="%Y%m%d.%H%M%S " export PROMPT_COMMAND='history -a;history -c;history -r' # /etc/rc.local # ------------- # eliminate older duplicates of history entries (HISTCONTROL=erasedups # works only occasionally), and keep backup files (in the past after # booting I found more than once surprisingly EMPTY ~/.bash_history, # probably because during previous shutdown multiple bash instances # tried to write simultanously and some failed) # --------------------------------------------- #!/bin/sh -e umask 0077 for Home in /root /home/* ; do if [ -f $Home/.bash_history ] ; then if [ -f $Home/.bash_history~0 ] ; then if [ -f $Home/.bash_history~1 ] ; then if [ -f $Home/.bash_history~2 ] ; then mv $Home/.bash_history~{2,3} fi mv $Home/.bash_history~{1,2} fi mv $Home/.bash_history~{0,1} fi mv $Home/.bash_history{,~0} fi sed -re 'N;s/\`#([0-9]+)\n/\1:/' $Home/.bash_history~0 \ | sed -re '/^[0-9]+:.{1,4}$/d' \ | sort -unr -t : -k 1,1 | sort -u -t : -k 2 | sort -n -t : -k 1,1 \ | sed -re 's/^([0-9]+):/#\1\n/' > "$Home/.bash_history" chown --reference "$Home" "$Home/.bash_history" done exit 0 HIGHLIGHT: ---------- first time hitting key UP and getting history of just used commandlines from OTHER terminals may be a bit confusing, after some familiarization you will probably enjoy it! SHORTCOMING: ------------ interactive "history -d" and "history -r" statements DON'T work, but luckily "vim $HISTFILE" WORKS Workaround 2: write separate history files for each $PID and terminal, consolidate them at next system boot ----------------------------------------------------------------------- NOT satisfying for me, bash history facilities buggy if filename $HISTFILE is longer than usual? (history -a takes NO effect, if HISTTIMEFORMAT is set history appears TWICE, ..) # /etc/bash.bashrc # ---------------- if [[ ! "${HISTFILE:-}" =~ .bash_history.[1-9] ]] ; then # keep already set $HISTFILE if we are sourced again within the same bash instance HISTFILE="$( mktemp "$HOME/.bash_history.$$.$( readlink -fn /proc/$$/fd/1 | sed 's,/dev/,,;s,/,,g' ).XXXXXX" )" # separate files, each file name showing $PID and terminal it belongs to fi # /etc/rc.local "normal version", assumes that there are # NO timestamps in history (HISTTIMEFORMAT not set) # ------------------------------------------------- #!/bin/sh -e umask 0077 for Home in /root /home/* ; do tDatei="$( mktemp "$Home/${0##*/}_bash_history.$$.XXXXXX" )" for BashHistory in $( find $Home -maxdepth 1 -name .bash_history.[1-9]\* -not -newer /var/log/boot -print0 | xargs -r -0 ls -tr ) ; do cat "$BashHistory" >> "$tDatei" rm "$BashHistory" done if [ -s "$tDatei" ] ; then [ -f $Home/.bash_history ] && mv $Home/.bash_history{,~0} gawk '/..../{print NR ":" $0;}' "$tDatei" | tac | sort -t : -k2 -u | sort -t : -k 1,1n | sed -r 's/^[0-9]+://' > "$Home/.bash_history" # remove command lines shorter than 4 characters, of duplicates keep only youngest chown -c --reference "$Home" "$Home/.bash_history" fi rm "$tDatei" done # SHORTCOMING: some NEW history entries appear at the beginning # of ~/.bash_history, but we want them at the end exit 0 # /etc/rc.local "DEBUGGING version", assumes that there are # NO timestamps in history (HISTTIMEFORMAT not set) # ------------------------------------------------- #!/bin/sh -e umask 0077 for Home in /root /home/* ; do tDatei="$( mktemp "$Home/${0##*/}_bash_history.$$.XXXXXX" )" for BashHistory in $( find $Home -maxdepth 1 -name .bash_history.[1-9]\* -not -newer /var/log/boot -print0 | xargs -r -0 ls -tr ) ; do cat "$BashHistory" >> "$tDatei" # rm "$BashHistory" echo "$BashHistory" # done done | tar -czf "${tDatei}.tgz" -T - --remove-files if [ -s "$tDatei" ] ; then [ -f $Home/.bash_history~2 ] && mv $Home/.bash_history~{2,3} [ -f $Home/.bash_history~1 ] && mv $Home/.bash_history~{1,2} [ -f $Home/.bash_history~0 ] && mv $Home/.bash_history~{0,1} [ -f $Home/.bash_history ] && mv $Home/.bash_history{,~0} gawk '/..../{print NR ":" $0;}' "$tDatei" | tac | sort -t : -k2 -u | sort -t : -k 1,1n | tee "${tDatei}.2" | sed -r 's/^[0-9]+://' > "$Home/.bash_history" # remove command lines shorter than 4 characters, of duplicates keep only youngest # chown -c --reference "$Home" "$Home/.bash_history" chown -c --reference "$Home" "$Home/.bash_history" "$tDatei"{,.2,.tgz} fi # rm "$tDatei" gzip -9 "$tDatei" done exit 0 _______________________________________________ Bug-bash mailing list Bug-bash@gnu.org http://lists.gnu.org/mailman/listinfo/bug-bash