[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bash overwrites most history entries, if several instances run simultano
From: |
Roland Eggner |
Subject: |
bash overwrites most history entries, if several instances run simultanously - WORKAROUND provided |
Date: |
Mon, 6 Aug 2007 02:19:28 +0200 |
User-agent: |
KMail/1.9.6 |
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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- bash overwrites most history entries, if several instances run simultanously - WORKAROUND provided,
Roland Eggner <=