Histórico de bash: as configurações de “ignorados” e “apagados” entram em conflito com o histórico comum entre as sessões

64

Primeiro de tudo, isso não é uma duplicata de quaisquer threads existentes no SE. Eu li esses dois tópicos ( 1a , 2nd ) no melhor histórico de bash, mas nenhuma das respostas funciona - - Estou no Fedora 15 pelo caminho.

Eu adicionei o seguinte ao arquivo .bashrc no diretório do usuário (/ home / aahan /), e ele não funciona. Alguém tem uma pista?

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

Ok, isso é o que eu quero com o histórico bash (prioridade):

  • não armazene duplicados, apague os existentes
  • compartilhe o histórico imediatamente com todos os terminais abertos
  • sempre anexar histórico, não substituí-lo
  • armazena comandos de várias linhas como um único comando (que está desativado por padrão)
  • qual é o tamanho do histórico e o tamanho do arquivo de histórico padrão?
por its_me 07.08.2011 / 05:52

4 respostas

102

Este é realmente um comportamento realmente interessante e confesso que subestimei a questão no começo. Mas primeiro os fatos:

1. O que funciona

A funcionalidade pode ser alcançada de várias maneiras, embora cada uma funcione de maneira um pouco diferente. Note que, em cada caso, para ter o histórico "transferido" para outro terminal (atualizado), deve-se pressionar Enter no terminal, onde ele deseja recuperar o histórico.

  • opção 1:

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

    Isso tem duas desvantagens:

    1. No login (abrindo um terminal), o último comando do arquivo de histórico é lido duas vezes no buffer de histórico do terminal atual;
    2. Os buffers de terminais diferentes não ficam sincronizados com o arquivo de histórico.
  • opção 2:

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

    (Sim, não há necessidade de shopt -s histappend e sim, tem que ser history -c no meio de PROMPT_COMMAND ) Esta versão também tem dois inconvenientes importantes:

    1. O arquivo de histórico deve ser inicializado. Tem que conter pelo menos uma linha não vazia (pode ser qualquer coisa).
    2. O comando history pode gerar saída falsa - veja abaixo.

[Editar]   "E o vencedor é ..."

  • opção 3:

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

    Isso é o máximo possível. É a opção somente para ter o erasedups e o histórico comum trabalhando simultaneamente. Esta é provavelmente a solução final para todos os seus problemas, Aahan.

2. Por que a opção 2 parece não funcionar (ou: o que realmente não funciona como esperado)?

Como mencionei, cada uma das soluções acima funciona de maneira diferente. Mas a interpretação mais equivocada de como as configurações funcionam vem da análise da saída de history command . Em muitos casos, o comando pode fornecer uma saída falsa . Por quê? Porque é executado antes da sequência de outros comandos history contidos no PROMPT_COMMAND ! No entanto, ao usar a segunda ou terceira opção, pode-se monitorar as mudanças de .bash_history contents (usando watch -n1 "tail -n20 .bash_history" por exemplo) e veja qual é a história real.

3. Por que a opção 3 é tão complicada?

Tudo está no modo erasedups funciona. Como afirma o manual bash, "(...) erasedups faz com que todas as linhas anteriores que correspondem à linha atual sejam removidas da lista de histórico antes que a linha seja salva" . Então, isso é realmente o que o OP queria (e não apenas, como eu pensava anteriormente, não ter duplicatas aparecendo em seqüência ) . Veja por que cada um dos comandos history -. tem ou não pode estar no PROMPT_COMMAND :

  • history -n tem para estar lá antes de history -w ler .bash_history dos comandos salvos de qualquer outro terminal,

  • history -w tem para estar lá, a fim de salvar o histórico para arquivar e apagar duplicatas,

  • history -a não deve ser colocado lá em vez de history -w , porque ele não aciona o apagamento de duplicatas,

  • history -c também é necessário porque evita a lixeira do buffer de histórico após cada comando,

  • e, finalmente, history -r é necessário para restaurar o buffer de histórico do arquivo, finalmente tornando o histórico compartilhado entre sessões de terminal.

por 10.08.2011 / 01:18
8

Em seu comando prompt, você está usando a opção -c . De man bash :

-c   Clear the history list by deleting all the entries

Para compartilhar seu histórico com todos os terminais abertos, você pode usar -n :

-n   Read the history lines not already read from the history file into the current history list. These are lines appended to the history file since the beginning of the current bash session.

O tamanho padrão também está no manual:

HISTSIZE The number of commands to remember in the command history (see HISTORY below). The default value is 500.

Para salvar comandos com várias linhas:

The cmdhist shell option, if enabled, causes the shell to attempt to save each line of a multi-line command in the same history entry, adding semicolons where necessary to preserve syntactic correctness. The lithist shell option causes the shell to save the command with embedded newlines instead of semicolons.

Além disso, você não deve introduzir os comandos HIST * com export - eles são apenas variáveis bash e não variáveis ambientais: HISTCONTROL=ignoredups:erasedups é suficiente.

    
por 07.08.2011 / 09:37
5

Isso é o que eu criei e estou feliz com isso até agora ...

alias hfix='history -n && history | sort -k2 -k1nr | uniq -f1 | sort -n | cut -c8- > ~/.tmp$$ && history -c && history -r ~/.tmp$$ && history -w && rm ~/.tmp$$'  
HISTCONTROL=ignorespace  
shopt -s histappend  
shopt -s extglob  
HISTSIZE=1000  
HISTFILESIZE=2000  
export HISTIGNORE="!(+(*\ *))"  
PROMPT_COMMAND="hfix; $PROMPT_COMMAND" 

NOTAS:

  • Sim, é complicado ... mas remove todos os duplicados e preserva a cronologia dentro de cada terminal!
  • Meu HISTIGNORE ignora todos os comandos que não possuem argumentos. Isso pode não ser desejável por algumas pessoas e pode ser deixado de fora.
por 14.06.2013 / 21:15
1

Use isso:

HISTCONTROL=ignoreboth
    
por 29.03.2012 / 19:23