2008-12-03 14 views
38

Ich versuche zu verhindern, dass bash doppelte Befehle in meinem Verlauf speichert. Hier ist, was ich habe:Verhindern, dass Duplikate in der Bash-History gespeichert werden

shopt -s histappend 
export HISTIGNORE='&:ls:cd ~:cd ..:[bf]g:exit:h:history' 
export HISTCONTROL=erasedups 
export PROMPT_COMMAND='history -a' 

Dies funktioniert gut, während ich angemeldet und .bash_history ist im Speicher. Zum Beispiel:

$ history 
    1 vi .bashrc 
    2 vi .alias 
    3 cd /cygdrive 
    4 cd ~jplemme 
    5 vi .bashrc 
    6 vi .alias 

$ vi .bashrc 

$ history 
    1 vi .alias 
    2 cd /cygdrive 
    3 cd ~jplemme 
    4 vi .alias 
    5 vi .bashrc 

$ vi .alias 

$ history 
    1 cd /cygdrive 
    2 cd ~jplemme 
    3 vi .bashrc 
    4 vi .alias 

$ exit 

Aber wenn ich wieder anmelden, meine History-Datei sieht wie folgt aus:

$ history 
    1 vi .bashrc 
    2 vi .alias 
    3 cd /cygdrive 
    4 cd ~jplemme 
    5 vi .bashrc 
    6 vi .alias 
    7 vi .bashrc 
    8 vi .alias 

Was mache ich falsch?

EDIT: Das Entfernen der shopt und PROMPT_COMMAND Zeilen von .bashrc behebt das Problem nicht.

+1

Haben Sie das jemals gelöst? Mein/etc/profile sieht so aus (auf einem Mac) und ich habe das gleiche Problem: # http://blog.macromates.com/2008/working-with-history-in-bash/ # http: //www.ducea.com/2006/05/15/linux-tips-take-control-of-your-bash_history/ Export HISTCONTROL = erasedups Export HISTSIZE = 10000 Export HISTTIMEFORMAT = "% F% T% t“ shopt es histappend (Den Versuch, diese Hälfte anständig zu formatieren, nicht leicht) – joedevon

+0

diese Frage Siehe http://unix.stackexchange.com/questions/48713/how-can-i-remove-duplicates -in-my-bash-history-erhaltende Reihenfolge – Nathan

+1

Dies ist ein inhärentes Problem in der Programmierung und bezieht sich auf spezifische Werkzeuge, die Programmierer verwenden. Ich bin verwirrt, dass diese Frage als "off-topic" (viel mehr von mindestens 5 Personen) betrachtet werden würde. Eine redundante .bash_history ist für mich seit langem ein Ärgernis, jetzt gelöst. Diese Frage konnte jedoch auf die Unix-Stackexchange-Site verschoben werden. –

Antwort

5
export HISTCONTROL=ignoreboth 
7

Das Problem ist definitiv die histappend. Getestet und bestätigt auf meinem System.

Meine relevante Umwelt ist:

$ set | grep HIST 
HISTFILE=/Users/hop/.bash_history 
HISTFILESIZE=500 
HISTIGNORE=' *:&:?:??' 
HISTSIZE=500 
$ export HISTCONTROL=erasedups 
$ shopt | grep hist 
cmdhist   on 
histappend  off 
histreedit  off 
histverify  off 
lithist   off 

Jetzt, wo ich darüber nachdenke, ist das Problem wahrscheinlich mit den history -a. history -w sollte den aktuellen Verlauf ohne Duplikate schreiben, verwenden Sie das also, wenn Sie die Nebenläufigkeitsprobleme nicht stören. Hier

2

ist, was ich benutze ..

[[email protected] ~]$ grep HIST .alias* 
.alias:HISTCONTROL="erasedups" 
.alias:HISTSIZE=20000 
.alias:HISTIGNORE=ls:ll:"ls -altr":"ls -alt":la:l:pwd:exit:mc:su:df:clear:ps:h:history:"ls -al" 
.alias:export HISTCONTROL HISTSIZE HISTIGNORE 
[[email protected] ~]$ 

und Arbeits

[[email protected] ~]$ pwd 
/Users/XXX 
[[email protected] ~]$ pwd 
/Users/XXX 
[[email protected] ~]$ history | grep pwd | wc -l 
     1 
+2

Danke Venu. Das Problem, das ich habe, ist ein bisschen anders. Nehmen wir an, es gibt 20 "ls" in der Geschichte. Durch Eingabe von "ls" werden Duplikate entfernt, sodass Ihr Verlauf kürzer ist ... zumindest während der Sitzung. Aber beenden und starten Sie eine neue Sitzung und es speichert die neuen Sachen und behält die alten Duplikate. Rückgängigmachen des größten Teils des Nutzens von Löschdämpfern. #Facepalm. – joedevon

+0

Angehängt etwas sehr ähnlich zu meinem .bash_profile: 'export HISTIGNORE = ls:" ls -la ":" cd .. ":" cd ~ ": pwd: verlassen: su:" sudo -i ": clear: ps: "ps $ export HISTSIZE = 20000 export HISTCONTROL =" löschtauchs "' – humbolight

1

in Ihrem .bash_profile hinzufügen

alias hist="history -a && hist.py" 

dann dies als hist.py auf Ihrem Weg setzen und mach es ausführbar

#!/usr/bin/env python 
f = open('/Users/joe/.bash_history') 
l = f.readlines() 
l.reverse() 
short = [] 
for s in l: 
    if s.rstrip() not in short: 
     short.append(s.rstrip()) 
short.reverse() 
for s in short: 
    print s 

jetzt, wenn Sie die kurze Liste möchten geben Sie einfach hist

31

Soweit ich weiß, ist es nicht möglich ist, zu tun, was Sie wollen. Ich sehe das als einen Fehler in der Geschichte Verarbeitung von bash, die verbessert werden könnte.

export HISTCONTROL=ignoreboth:erasedups # no duplicate entries 
shopt -s histappend      # append history file 
export PROMPT_COMMAND="history -a"  # update histfile after every command 

Dies wird die in Erinnerung Geschichte einzigartig halten, aber während es Geschichte tut spart aus mehreren Sitzungen in der gleichen Datei, halten sie nicht die Geschichte in der Datei selbst einzigartig. history -a schreibt den neuen Befehl in die Datei, es sei denn, es ist derselbe wie der unmittelbar davor. Es wird nicht eine vollständige Deduplizierung wie die erasedups Einstellung im Speicher tun.

Um diese Dummheit in Aktion zu sehen, starten Sie eine neue Terminalsitzung, untersuchen Sie den Verlauf, und Sie werden wiederholt Einträge sehen, sagen ls. Führen Sie jetzt den Befehl ls aus, und alle duplizierten ls werden aus dem Verlauf im Speicher gelöscht, wobei nur der letzte zurückbleibt. Der In-Memory-Verlauf wird kürzer, wenn Sie Befehle ausführen, die in der History-Datei dupliziert sind, aber die History-Datei selbst wächst weiter.

Ich benutze mein eigenes Skript, um die Verlaufsdatei bei Bedarf zu bereinigen.

# remove duplicates while preserving input order 
function dedup { 
    awk '! x[$0]++' [email protected] 
} 

# removes $HISTIGNORE commands from input 
function remove_histignore { 
    if [ -n "$HISTIGNORE" ]; then 
     # replace : with |, then * with .* 
     local IGNORE_PAT=`echo "$HISTIGNORE" | sed s/\:/\|/g | sed s/\*/\.\*/g` 
     # negated grep removes matches 
     grep -vx "$IGNORE_PAT" [email protected] 
    else 
     cat [email protected] 
    fi 
} 

# clean up the history file by remove duplicates and commands matching 
# $HISTIGNORE entries 
function history_cleanup { 
    local HISTFILE_SRC=~/.bash_history 
    local HISTFILE_DST=/tmp/.$USER.bash_history.clean 
    if [ -f $HISTFILE_SRC ]; then 
     \cp $HISTFILE_SRC $HISTFILE_SRC.backup 
     dedup $HISTFILE_SRC | remove_histignore >| $HISTFILE_DST 
     \mv $HISTFILE_DST $HISTFILE_SRC 
     chmod go-r $HISTFILE_SRC 
     history -c 
     history -r 
    fi 
} 

Ich würde gerne elegantere Möglichkeiten, dies zu tun hören.

Hinweis: Das Skript funktioniert nicht, wenn Sie den Zeitstempel im Verlauf über HISTTIMEFORMAT aktivieren. in Erinnerung, nicht nur die letzten

Bash kann die Situation von

  1. fix history -a nur neue Daten schreiben verbessern, wenn es keine Geschichte übereinstimmt.
  2. deduplizieren Geschichte, wenn Dateien gelesen werden, wenn erasedups Einstellung festgelegt ist. Ein einfacher history -w in einem neuen Terminal würde dann die Verlaufsdatei anstelle des obigen dummen Skripts bereinigen.
+3

Ausgezeichnete Antwort.Wenn Sie lieber die chronologische Reihenfolge (anstelle der Reihenfolge der Eingabe) für Ihre Befehle beibehalten möchten, ändern Sie 'dedup()' durch Ersetzen von 'awk ' ! x [$ 0] ++ '$ @ 'mit' tac $ @ | awk'! x [$ 0] ++ '| tac'. – trusktr

+6

@raychi Nur um zu sehen, ob dies immer noch die beste Lösung ist, wie wir uns 2014 nähern ? –

+1

@ @ trusktrs Kommentar erweitern, das 'history -a' zu reparieren, um nur neue Daten zu schreiben, würde auch nicht funktionieren, da es eigentlich das vorherige Ereignis entfernen und das letzte hinzufügen sollte. Ich vermute, dass es aufgrund dieser Komplexität ist, dass sie ' haben sich dafür entschieden, nur aufeinanderfolgende Duplikate zu entfernen. – trss