GNU/Linux >> Znalost Linux >  >> Linux

Historie Bash:„ignoredups“ a „erasedups“ Nastavení konfliktu se společnou historií napříč relacemi?

Za prvé, toto není duplikát žádného existujícího vlákna na SE. Četl jsem tato dvě vlákna (1., 2.) o lepší historii bash, ale žádná z odpovědí nefunguje – – mimochodem jsem na Fedoře 15.

Do souboru .bashrc jsem přidal následující soubor v uživatelském adresáři (/home/aahan/) a nefunguje to. Má někdo tušení?

HISTCONTROL=ignoredups:erasedups  # no duplicate entries
HISTSIZE=1000                     # custom history size
HISTFILESIZE=100000                 # custom history file size
shopt -s histappend                      # append to history, don't overwrite it
PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"  # Save and reload the history after each command finishes

Dobře, to je to, co chci s historií bash (priorita):

  • neuchovávejte duplikáty, vymažte všechny existující
  • okamžitě sdílet historii se všemi otevřenými terminály
  • historii vždy připojujte, nikoli ji přepisujte
  • ukládat víceřádkové příkazy jako jeden příkaz (který je ve výchozím nastavení vypnutý)
  • jaká je výchozí velikost historie a velikost souboru historie?

Přijatá odpověď:

To je ve skutečnosti opravdu zajímavé chování a přiznám se, že jsem otázku na začátku značně podcenil. Ale nejprve fakta:

1. Co funguje

Funkčnosti lze dosáhnout několika způsoby, i když každý funguje trochu jinak. Všimněte si, že v každém případě, aby byla historie „přenesena“ na jiný terminál (aktualizována), musíte stisknout Enter v terminálu, kde chce načíst historii.

  • možnost 1:

     shopt -s histappend
     HISTCONTROL=ignoredups
     PROMPT_COMMAND="history -a; history -n; $PROMPT_COMMAND"
    

To má dvě nevýhody:

  1. Při přihlášení (otevření terminálu) je poslední příkaz ze souboru historie načten dvakrát do vyrovnávací paměti historie aktuálního terminálu;
  2. Vyrovnávací paměti různých terminálů nezůstávají synchronizované se souborem historie.
  • možnost 2:

     HISTCONTROL=ignoredups
     PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
    

(Ano, není potřeba shopt -s histappend a ano, musí být history -c uprostřed příkazu PROMPT_COMMAND )
Tato verze má také dvě důležité nevýhody:

  1. Soubor historie musí být inicializován. Musí obsahovat alespoň jeden neprázdný řádek (může být cokoli).
  2. history příkaz může poskytnout falešný výstup – viz níže.

[Upravit] „A vítězem je…“

  • Možnost 3:

     HISTCONTROL=ignoredups:erasedups
     shopt -s histappend
     PROMPT_COMMAND="history -n; history -w; history -c; history -r; $PROMPT_COMMAND"
    

To je tak daleko, jak to jde. Je to jediné možnost mít obě erasedups a společná historie fungující současně. Toto je pravděpodobně konečným řešením všem tvým problémům, Aahane.

2. Proč možnost 2 Zdá se, že nefunguje (nebo:co skutečně nefunguje podle očekávání)?

Jak jsem již zmínil, každé z výše uvedených řešení funguje jinak. Ale nejvíc zavádějící interpretace toho, jak nastavení fungují, pochází z analýzy výstupu history příkaz . V mnoha případech může mít příkaz hodnotu false výstup. Proč? Protože je spuštěna před posloupnost další history příkazy obsažené v PROMPT_COMMAND ! Při použití druhé nebo třetí možnosti však lze sledovat změny .bash_history obsah (pomocí watch -n1 "tail -n20 .bash_history" například) a podívejte se, jaká je skutečná historie.

Související:Proč se výstupní napětí generátoru signálu mění s jeho nastavením frekvence?

3. Proč možnost 3 je to tak složité?

Vše spočívá ve způsobu erasedups funguje. Jak uvádí příručka bash, “(…) erasedups způsobí, že všechny předchozí řádky odpovídající aktuálnímu řádku budou odstraněny ze seznamu historie před uložením tohoto řádku“ . Takže to je opravdu to, co OP chtěl (a nejen, jak jsem si dříve myslel, aby se žádné duplikáty neobjevovaly v pořadí ) . Zde je důvod, proč každá z history -. příkazy buď musí, nebo nemohou být v PROMPT_COMMAND :

  • history -n být tam před history -w ke čtení z .bash_history příkazy uložené z jakéhokoli jiného terminálu,

  • history -w být tam a uložit novou historii do souboru poté, co bash zkontroluje, zda je příkaz duplicitní,

  • history -a nesmí být tam umístěn místo history -w , protože do souboru přidá jakýkoli nový příkaz, bez ohledu na to, zda byl zaškrtnut jako duplikát.

  • history -c je také potřebné protože zabraňuje vymazání vyrovnávací paměti historie po každém příkazu,

  • a nakonec history -r je potřebný obnovit vyrovnávací paměť historie ze souboru, čímž se historie konečně sdílí mezi terminálovými relacemi.

Uvědomte si, že toto řešení naruší pořadí historie tím, že veškerou historii z jiných terminálů vloží před nejnovější příkaz zadaný v aktuálním terminálu. Rovněž neodstraní duplicitní řádky již v souboru historie, pokud tento příkaz nezadáte znovu.


Linux
  1. Použití slovních modifikátorů s historií Bash v Linuxu

  2. Jak zachytit terminálové relace a výstup pomocí příkazu skriptu Linux

  3. Hromadné přejmenování souboru Bash pomocí čítače?

  1. Pomocí historie bash získáte předchozí příkaz, zkopírujte jej a poté jej „spusťte“, ale s komentářem příkazu

  2. echo text s novým řádkem v bash

  3. Jak uchovám historii bash napříč relacemi?

  1. Udělejte z historie Bash užitečnější pomocí těchto tipů

  2. Jak programovat s Bash:Syntaxe a nástroje

  3. Odstraňte určitý řádek ze souboru historie Bash