É possível tornar a escrita em .bash_history imediata?

125

Eu muitas vezes abertas e lotes de terminais [Agora eu tenho 7 aberto neste espaço de trabalho] e muitas vezes eu procurar historycom greppara encontrar um comando Acabo de escrever recentemente, mas eu não quero caçar o terminal e, em seguida, vá para cima e caçar mais, etc. Às vezes, meus terminais fecham sem 'saída' e tudo o que escrevi se perde [às vezes eu precisava de algo que escrevi em um terminal que foi morto].

Portanto, existe uma maneira de fazê-lo para que cada terminal grave imediatamente no .bash_history? ou pelo menos uma vez por minuto, ou algo assim?

Matt
fonte
2
Normalmente, eu uso control-ra pesquisa reversa no histórico de comandos de um bash. Mais conveniente do que a history | grepmenos que você precise de uma regex.
Peter Cordes

Respostas:

93

Uma solução simples, conforme detalhado no histórico de atualizações do Bash em tempo real .

Ele diz para colocar esses comandos na configuração .bashrc:

shopt -s histappend
PROMPT_COMMAND="history -a;$PROMPT_COMMAND"

O primeiro comando altera o .historymodo de arquivo para acrescentar. E o segundo configura o history -acomando a ser executado em cada prompt do shell. Ele -agrava imediatamente as linhas atuais / novas no arquivo de histórico.

Relacionado para zsh:

mario
fonte
1
Bem, este tipo de obras. Eu tentei mais alguns testes e parece funcionar apenas no primeiro comando. funciona corretamente para você?
Matt
55

Tente colocar isso no seu .bashrc:

shopt -s histappend                      # append to history, don't overwrite it
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

Crédito aqui: https://stackoverflow.com/questions/103944/real-time-history-export-amongst-bash-terminal-windows/3055135

history -climpa o histórico da sessão em execução. Isso reduzirá o contador de histórico pela quantidade de $HISTSIZE. history -rleia o conteúdo $HISTFILEe insira-o no histórico atual da sessão em execução. Isso aumentará o contador do histórico pela quantidade de linhas inseridas $HISTFILE.

Eu acho que isso significa que os comandos estão disponíveis quase que imediatamente (você tem um terminal, gravação echo 1, segundo terminal echo 2, primeiro echo 3e, pressionando a seta para baixo duas vezes, você deve ter echo 2disponível. Você deve emitir um comando em um determinado terminal para ter acesso ao que possui foi escrito.

sup
fonte
Brilhante! Obrigado. Pergunto-me por que essas opções não estão documentadas em man history... #
1813
10
@artfulrobot: Este comando é um bashbuilt-in, portanto é descrito em man bash. Você também pode usar help history.
pabouk
2
Eu tenho o meu zsh configurado para funcionar assim: cada shell rastreia seu próprio histórico (e antes disso, o histórico combinado) e todo comando é anexado ao histórico combinado. Isso é diferente e melhor do que sempre recarregar o histórico para cada comando para cada shell, porque eu tendem a ter um "thread de trabalho" ou "job" diferente para cada terminal do shell. Eu acho que é a diferença entre isso com -re -cvs apenas ter -a.
Steven Lu
Então, o que exatamente você está usando? history -c; history -r? Eu acho que é melhor para você, seria melhor para mim apenas algumas vezes, eu geralmente uso várias conchas para fazer um trabalho, então prefiro ter a história o mais combinada possível. Na verdade, eu me importo que o comando seja gravado na história somente depois que terminar. Normalmente, quando inicio uma sessão ssh em um host e quero abrir outro enquanto o primeiro ainda está em execução, preciso digitá-lo novamente, porque ainda não foi gravado no histórico.
2525
Eu acho que nunca fiquei tempo suficiente para descobrir como fazer o bash rastrear simultaneamente threads paralelos do histórico (por base de instância do shell) enquanto escrevia o histórico imediatamente no arquivo de histórico principal. O Zsh facilita muito isso, além disso, defini uma função zsh para escrever muitos metadados sofisticados em um arquivo de histórico aprimorado da minha criação. Tornou-se bastante indispensável. De qualquer forma, o mecanismo lá é precmd () e preexec () para zsh recebem argumentos que descrevem o comando digitado. Torna-se trivial direcionar isso para arquivos. history -apode bastar
Steven Lu
38

Eu tenho um arquivo de histórico grande com cerca de 100000 entradas e as variantes que limpam a lista de histórico e leem o arquivo de histórico inteiro (usando history -ce history -r) apresentam um atraso notável (talvez 0,2 segundo) antes que o prompt seja exibido. Usar history -npara que apenas novas linhas sejam lidas do arquivo de histórico é mais rápido:

shopt -s histappend
PROMPT_COMMAND='history -a;history -n'

PROMPT_COMMAND não precisa ser exportado porque é uma variável de shell.

nisetama
fonte
Brilhante! Não há mais histórico perdido quando a conexão cai!
precisa saber é
Isso é maravilhoso. Ao anexar ao arquivo e ler o arquivo, ele compartilhará o histórico em vários terminais.
23618 wisbucky
3

Uma observação para todas as outras respostas (que são basicamente a mesma coisa):

Definir PROMPT_COMMAND="history -a;$PROMPT_COMMAND"no .bashrc(ou amigos) é suficiente.

Além disso, você pode executar manualmente history -asempre que desejar "capturar instantaneamente" o histórico na sessão atual.

O comando shopt -s histappendnão é necessário porque history -asempre acrescenta novas linhas ao arquivo e nunca o substitui. Além disso, pelo menos a partir do Bash 4, histappendé o comportamento padrão.

Guss
fonte
No meu mac 10.13.6, parecia que não funcionava sem o shopt -s histappend. Observe também eu adicionei-o ao meu~/.bash_profile
ubershmekel
Provavelmente, há outra configuração em algum lugar do sistema que foi desativada histappend, pois esse é o comportamento padrão. Eu procuraria, mas não tenho acesso a um Mac.
Guss