Preserve o histórico do bash em várias janelas de terminal

525

Consistentemente, tenho mais de um terminal aberto. Em qualquer lugar de duas a dez, fazendo várias coisas. Agora, digamos que eu reinicie e abro outro conjunto de terminais. Alguns se lembram de certas coisas, outros se esquecem.

Eu quero uma história que:

  • Lembra de tudo, de todos os terminais
  • É acessível instantaneamente a partir de qualquer terminal (por exemplo, se eu estiver lsem um, alterne para outro terminal já em execução e pressione, lsaparece)
  • Não se esqueça do comando se houver espaços na frente do comando.

Qualquer coisa que eu possa fazer para que o bash funcione dessa maneira?

Oli
fonte
57
Eu posso ver a vantagem disso, mas pessoalmente eu odiaria isso no meu shell. Normalmente, mantenho 3 ou 4 abas abertas no meu terminal para usos muito específicos: uma para executar 'make', uma com vi, outra para executar coisas, etc. 'aparece, e assim por diante. Isso é extremamente produtivo para mim. Então, se de repente eu for para a aba 'make' e apertar e algum comando grep aleatório aparecer, eu ficaria realmente chateado! Apenas uma observação pessoal
axel_c 26/08/10
4
@axel_c isso é verdade. Não consigo pensar em uma maneira inteligente de fazê-lo, onde os terminais existentes apenas veem seu próprio histórico, mas os novos veem uma lista cronologicamente precisa de comandos.
Oli
8
@Oli escreveu: "Não consigo pensar em uma maneira inteligente de fazê-lo, onde os terminais existentes apenas veem seu próprio histórico, mas os novos veem uma lista cronologicamente precisa de comandos". Que tal (inexperiente): export PROMPT_COMMAND="history -a; $PROMPT_COMMAND". Os shells existentes adicionarão cada comando ao arquivo de histórico para novos shells verem, mas mostrarão apenas seus próprios históricos.
Chris Página
2
Deseja que o histórico seja todo armazenado separadamente ou mesclado em um único arquivo de histórico?
kbyrd
3
A resposta curta é: não é pretendida pelos desenvolvedores do bash. Soluções baseadas na descarga e depois relendo a história provavelmente funcionam, mas cuidado com o Shlemiel The Painter . Em palavras simples: a quantidade de trabalho de processamento entre cada comando é proporcional ao tamanho do histórico.
Stéphane Gourichon

Respostas:

328

Adicione o seguinte ao ~ / .bashrc

# Avoid duplicates
export HISTCONTROL=ignoredups:erasedups  
# When the shell exits, append to the history file instead of overwriting it
shopt -s histappend

# After each command, append to the history file and reread it
export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"
Pablo R.
fonte
20
O problema com esta solução PROMPT_COMMAND é que os números para cada item do histórico são alterados após cada comando :(. Por exemplo, se você digitar histórico e 1) ls 2) rm, então você faz! 1 para repetir 1, o número do histórico pode mudar e pode executar o comando rm ...
Chris Kimpton
2
Quando faço isso, outros terminais já abertos não têm o último comando digitado quando pressiono 'Up' até depois de emitir um comando nesse terminal - isso é esperado? Em caso afirmativo, existe uma maneira de modificar verdadeiramente o histórico de outros terminais instantaneamente?
Suan
7
@Suan, isso parece certo para mim com base nos comandos. Descobri que podemos emitir um comando nulo (basta pressionar a tecla Enter) para atualizar o histórico.
sage
3
Na verdade history -a(...) não aciona a exclusão de duplicatas, de acordo com esta resposta à pergunta Histórico do Bash: "ignororedups" e "apagados", configurando conflito com o histórico comum em todas as sessões . Esta resposta também fornece a sequência de history -<option>comandos que funciona com a HISTCONTROL=ignoredups:erasedupsconfiguração.
Piotr Dobrogost
23
Não há razão para exportas variáveis HISTCONTROLe PROMPT_COMMAND: você as define .bashrcpara que elas sejam definidas em todos os shell (mesmo nos não interativos, o que também é um desperdício).
dólmen
248

Então, isso é tudo relacionado à história .bashrc:

export HISTCONTROL=ignoredups:erasedups  # no duplicate entries
export HISTSIZE=100000                   # big big history
export HISTFILESIZE=100000               # big big history
shopt -s histappend                      # append to history, don't overwrite it

# Save and reload the history after each command finishes
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

Testado com o bash 3.2.17 no Mac OS X 10.5, o bash 4.1.7 no 10.6.

kch
fonte
3
Hmm .. Isso mata a capacidade de usar $! 34, pois os números de comando mudam a cada prompt. Existe uma solução alternativa para @Davide @Schof @kch?
5
Use isso para obter uma história infinita: bash a história eterna . NO ENTANTO, isso é complementar ao código acima, pois não será recarregado automaticamente.
7
FYI Nenhuma das soluções mencionadas aqui pode resolver o seguinte problema. Eu tenho duas janelas de shell A e B. Na janela de shell A, eu corro sleep 9999e (sem esperar o término do sono) na janela de shell B, quero poder ver sleep 9999no histórico do bash.
pts
1
@pts Eu também estava buscando comportamento ao vivo, mas então percebi que é mais conveniente ter históricos específicos de terminais que facilitem o trabalho em coisas diferentes em diferentes terminais. Achei isso muito útil: stackoverflow.com/questions/338285/#answer-7449399 Com base nisso, criei um apelido chamado hrefque atualiza o histórico do meu terminal atual instantaneamente e limpa o arquivo do histórico no processo. Sempre que abro um novo terminal, essa limpeza / sincronização é executada no meu arquivo bashrc para que o novo terminal tenha o histórico mais recente. Eu estou usando isso junto comhistory -a
trusktr
6
Não há nenhuma razão para exportas variáveis: você está definindo-os em .bashrcque eles serão definidos em cada shell (mesmo nas não-interativas, o que representa um desperdício)
dólmen
117

Aqui está minha tentativa de compartilhar o histórico de sessões do Bash. Isso permitirá o compartilhamento do histórico entre as sessões do bash de uma maneira que o contador do histórico não se confunda e a expansão do histórico !numberfuncione (com algumas restrições).

Usando o Bash versão 4.1.5 no Ubuntu 10.04 LTS (Lucid Lynx).

HISTSIZE=9000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups

_bash_history_sync() {
    builtin history -a         #1
    HISTFILESIZE=$HISTSIZE     #2
    builtin history -c         #3
    builtin history -r         #4
}

history() {                  #5
    _bash_history_sync
    builtin history "$@"
}

PROMPT_COMMAND=_bash_history_sync

Explicação:

  1. Anexe a linha recém-inserida ao $HISTFILE(o padrão é .bash_history). Isso fará $HISTFILEcrescer uma linha.

  2. Definir a variável especial $HISTFILESIZEcom algum valor fará com que o Bash trunque $HISTFILEnão exceda as $HISTFILESIZElinhas removendo as entradas mais antigas.

  3. Limpe o histórico da sessão em execução. Isso reduzirá o contador de histórico pela quantidade de $HISTSIZE.

  4. Leia 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. Observe que a contagem de linhas de $HISTFILEnão é necessariamente $HISTFILESIZE.

  5. A history()função substitui o histórico interno para garantir que o histórico seja sincronizado antes de ser exibido. Isso é necessário para a expansão do histórico por número (mais sobre isso posteriormente).

Mais explicações:

  • A etapa 1 garante que o comando da sessão atual seja gravado no arquivo de histórico global.

  • A Etapa 4 garante que os comandos das outras sessões sejam lidos no histórico de sessões atual.

  • Como a etapa 4 elevará o contador do histórico, precisamos reduzir o contador de alguma forma. Isso é feito na etapa 3.

  • Na etapa 3, o contador de histórico é reduzido em $HISTSIZE. Na etapa 4, o contador de histórico é aumentado pelo número de linhas em $HISTFILE. Na etapa 2, garantimos que a contagem de linhas de $HISTFILEseja exatamente $HISTSIZE(isso significa que $HISTFILESIZEdeve ser o mesmo $HISTSIZE).

Sobre as restrições da expansão do histórico:

Ao usar a expansão do histórico por número, você deve sempre procurar o número imediatamente antes de usá-lo. Isso significa que nenhum prompt do bash será exibido entre procurar o número e usá-lo. Isso geralmente significa não entrar e não ctrl + c.

Geralmente, depois de ter mais de uma sessão do Bash, não há garantia de que uma expansão de histórico por número retenha seu valor entre duas exibições de prompt do Bash. Como quando PROMPT_COMMANDé executado, o histórico de todas as outras sessões do Bash é integrado ao histórico da sessão atual. Se qualquer outra sessão do bash tiver um novo comando, os números do histórico da sessão atual serão diferentes.

Acho essa restrição razoável. De qualquer forma, tenho que procurar o número sempre, porque não consigo me lembrar de números arbitrários do histórico.

Normalmente eu uso a expansão do histórico por número como este

$ history | grep something #note number
$ !number

Eu recomendo usar as seguintes opções do Bash.

## reedit a history substitution line if it failed
shopt -s histreedit
## edit a recalled history line before executing
shopt -s histverify

Erros estranhos:

A execução do comando history canalizado para qualquer coisa fará com que esse comando seja listado duas vezes no histórico. Por exemplo:

$ history | head
$ history | tail
$ history | grep foo
$ history | true
$ history | false

Todos serão listados no histórico duas vezes. Eu não tenho ideia do porquê.

Ideias para melhorias:

  • Modifique a função _bash_history_sync()para que ela não seja executada todas as vezes. Por exemplo, ele não deve ser executado após um CTRL+Cprompt. Costumo usar CTRL+Cpara descartar uma longa linha de comando quando decido que não quero executar essa linha. Às vezes, tenho que usar CTRL+Cpara interromper um script de conclusão do Bash.

  • Os comandos da sessão atual devem sempre ser os mais recentes no histórico da sessão atual. Isso também terá o efeito colateral de que um determinado número de histórico mantenha seu valor para as entradas de histórico desta sessão.

lesmana
fonte
1
Por que não "history -n" (recarregar linhas ainda não carregadas) em vez de "history -c; history -r"?
Graham
@ Graham: Eu não queria usar history -nporque isso atrapalha o contador de histórico. Além disso, eu achei history -nmuito confiável.
lesmana
1
Uma desvantagem: os comandos com sequências de várias linhas normalmente ainda são preservados na sessão atual. Com esse truque, eles são divididos em linhas individuais instantaneamente. Usar -n para -c -r não ajuda, nem cmdhist ou litista. Eu não acho que há uma solução alternativa neste momento.
Jo Liss
24
Depois de tentar isso um pouco, descobri que rodar apenas history -a, sem -ce -r, é melhor em termos de usabilidade (embora não seja o que a pergunta foi feita). Isso significa que os comandos executados estão disponíveis instantaneamente em novos shells, mesmo antes de sair do shell atual, mas não nos shells em execução simultânea. Dessa forma, o Arrow-Up ainda sempre seleciona os comandos de última execução da sessão atual , o que acho muito menos confuso.
Jo # Liss
excepcionalmente boa resposta, isso funciona de maneira confiável, diferentemente da "história -a; história -n" mais comum
RichVel
42

Eu não estou ciente de nenhuma maneira de usar bash. Mas é um dos recursos mais populares do zsh.
Pessoalmente, prefiro zshmais, bashentão recomendo tentar.

Aqui está a parte do meu .zshrcque lida com a história:

SAVEHIST=10000 # Number of entries
HISTSIZE=10000
HISTFILE=~/.zsh/history # File
setopt APPEND_HISTORY # Don't erase history
setopt EXTENDED_HISTORY # Add additional data to history like timestamp
setopt INC_APPEND_HISTORY # Add immediately
setopt HIST_FIND_NO_DUPS # Don't show duplicates in search
setopt HIST_IGNORE_SPACE # Don't preserve spaces. You may want to turn it off
setopt NO_HIST_BEEP # Don't beep
setopt SHARE_HISTORY # Share history between session/terminals
Maciej Piechotka
fonte
16

Para fazer isso, você precisará adicionar duas linhas ao seu ~/.bashrc:

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

De man bash:

Se a opção shell histappend estiver ativada (consulte a descrição do shopt em SHELL BUILTIN COMMANDS abaixo), as linhas serão anexadas ao arquivo de histórico, caso contrário, o arquivo de histórico será sobrescrito.

Chris Down
fonte
10

Você pode editar seu prompt do BASH para executar os "history -a" e "history -r" que Muerr sugeriu:

savePS1=$PS1

(no caso de você estragar alguma coisa, o que é quase garantido)

PS1=$savePS1`history -a;history -r`

(observe que esses são back-tiquetaques; eles executam o histórico -a e o histórico -r em cada prompt. Como não produzem nenhum texto, o prompt será inalterado.

Depois de configurar sua variável PS1 da maneira que desejar, defina-a permanentemente no seu arquivo ~ / .bashrc.

Se você quiser voltar ao prompt original durante o teste, faça:

PS1=$savePS1

Fiz testes básicos para garantir que funcione, mas não consigo falar com nenhum efeito colateral ao executar history -a;history -rem todos os prompt.

Schof
fonte
2
A solução da kch funciona melhor que a minha. Agora estou usando a solução dele no meu .bashrc.
9

Se você precisar de uma solução de sincronização de histórico do bash ou zsh que também resolva o problema abaixo, consulte-o em http://ptspts.blogspot.com/2011/03/how-to-automatically-synchronize-shell.html

O problema é o seguinte: Eu tenho duas janelas de shell A e B. Na janela de shell A, eu corro sleep 9999e (sem esperar o término do sono) na janela de shell B, quero poder ver sleep 9999no histórico do bash.

A razão pela qual a maioria das outras soluções aqui não resolve esse problema é que elas estão gravando as alterações de histórico no arquivo de histórico usando PROMPT_COMMANDou PS1, sendo que as duas estão sendo executadas tarde demais, somente após a conclusão do sleep 9999comando.

pts
fonte
1
Esta é uma boa solução, mas tenho algumas perguntas. 1. Posso usar o arquivo .bash_history original, não quero que exista outro arquivo de histórico do bash no meu $ HOME 2. Pode ser que você deva considerar definir um repositório do github para isso.
weynhamz
Parece que o gancho de depuração está em conflito com o bashdb, a saída a seguir toda vez que inicio uma sessão do bash. `` `bash depurador, bashdb, versão 4.2-0.8 Copyright 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Rocky Bernstein Este é um software livre, coberto pela GNU General Public License, e você é bem-vindo ao altere-o e / ou distribua cópias sob determinadas condições. ** Erro de depuração interna _Dbg_is_file (): arquivo argumento nulo bash: _Dbg_filenames [$ fullname]: matriz
inválida
@Techlive Zheng: 1. O .bash_history original não é deliberadamente suportado, porque .merged_bash_history usa um formato de arquivo diferente; portanto, caso o .merged_bash_history falhe ao carregar corretamente, o bash não obstruirá acidentalmente o histórico acumulado. A robustez por design será mantida como está. 2. Um repositório do github é uma boa ideia em geral, mas não tenho tempo para mantê-lo nesse projeto, por isso não o faço. - Sim, entra em conflito com o bashdb e não há solução fácil (eles usam os mesmos ganchos). Não estou planejando trabalhar em uma correção, mas estou aceitando patches.
Pts
Ok, obrigada. Eu vim com um sulotion muito simples e melhor.
weynhamz
@TechliveZheng: Você compartilharia sua solução simples e melhor conosco, para que todos possamos aprender com ela? (Se sim, por favor, adicionar uma resposta para a pergunta.)
pts
8

Você pode usar history -apara anexar o histórico da sessão atual ao arquivo de histórico e, em seguida, usar history -rnos outros terminais para ler o arquivo de histórico. 

jtimberman
fonte
8

Certo, então finalmente isso me incomodou em encontrar uma solução decente:

# Write history after each command
_bash_history_append() {
    builtin history -a
}
PROMPT_COMMAND="_bash_history_append; $PROMPT_COMMAND"

O que isso faz é uma espécie de amálgama do que foi dito neste segmento, exceto que eu não entendo por que você recarregaria a história global após cada comando. Eu raramente me importo com o que acontece em outros terminais, mas sempre executo uma série de comandos, digamos em um terminal:

make
ls -lh target/*.foo
scp target/artifact.foo vm:~/

(Exemplo simplificado)

E em outro:

pv ~/test.data | nc vm:5000 >> output
less output
mv output output.backup1

De jeito nenhum eu gostaria que o comando fosse compartilhado

Yarek T
fonte
1
A razão pela qual você recarregaria o histórico após cada comando é que é o comportamento exigido pela pergunta (e, portanto, isso realmente não responde à pergunta como colocada).
Michael Homer
2
@MichaelHomer Fair point. Sinta-se à vontade para fazer um voto negativo, para que a resposta fique na parte inferior, no entanto, eu atribuiria isso ao OP, sem perceber o quão ruim o comportamento solicitado seria e o fato de que essa é uma pergunta muito complicada.
Yarek T
3
Aqui, sim, é um compromisso justo. Minha principal reclamação é que eu estava perdendo a história. Isso deve impedir isso, mesmo que isso não signifique atualizações instantâneas em sessões simultâneas.
Oli
7

Aqui está uma alternativa que eu uso. É complicado, mas aborda o problema que o @axel_c mencionou onde às vezes você pode querer ter uma instância de histórico separada em cada terminal (um para make, outro para monitoramento, outro para vim, etc.).

Eu mantenho um arquivo de histórico anexado separado que atualizo constantemente. Eu tenho o seguinte mapeado para uma tecla de atalho:

history | grep -v history >> ~/master_history.txt

Isso anexa todo o histórico do terminal atual a um arquivo chamado master_history.txt no seu diretório pessoal.

Também tenho uma tecla de atalho separada para pesquisar no arquivo de histórico mestre:

cat /home/toby/master_history.txt | grep -i

Eu uso gato | grep porque deixa o cursor no final para inserir meu regex. Uma maneira menos feia de fazer isso seria adicionar alguns scripts ao seu caminho para realizar essas tarefas, mas as teclas de atalho funcionam para meus propósitos. Periodicamente, também retirarei o histórico de outros hosts em que trabalhei e anexarei esse histórico ao meu arquivo master_history.txt.

É sempre bom poder pesquisar rapidamente e encontrar o regex complicado que você usou ou o one-liner perl estranho que você inventou há 7 meses.

Toby
fonte
6

Posso oferecer uma correção para essa última: verifique se a variável env HISTCONTROL não especifica "ignorespace" (ou "ignoreboth").

Mas sinto sua dor com várias sessões simultâneas. Simplesmente não é bem tratado no bash.

jmanning2k
fonte
6

Aqui está o meu aprimoramento na resposta de @ lesmana . A principal diferença é que as janelas simultâneas não compartilham histórico. Isso significa que você pode continuar trabalhando nas janelas, sem ter o contexto de outras janelas sendo carregado nas janelas atuais.

Se você digitar explicitamente 'history', OU se abrir uma nova janela, obterá o histórico de todas as janelas anteriores.

Além disso, uso essa estratégia para arquivar todos os comandos já digitados na minha máquina.

# Consistent and forever bash history
HISTSIZE=100000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups

_bash_history_sync() {
  builtin history -a         #1
  HISTFILESIZE=$HISTSIZE     #2
}

_bash_history_sync_and_reload() {
  builtin history -a         #1
  HISTFILESIZE=$HISTSIZE     #2
  builtin history -c         #3
  builtin history -r         #4
}

history() {                  #5
  _bash_history_sync_and_reload
  builtin history "$@"
}

export HISTTIMEFORMAT="%y/%m/%d %H:%M:%S   "
PROMPT_COMMAND='history 1 >> ${HOME}/.bash_eternal_history'
PROMPT_COMMAND=_bash_history_sync;$PROMPT_COMMAND
rublo
fonte
5

Eu escolhi colocar o histórico em um arquivo por tty, pois várias pessoas podem trabalhar no mesmo servidor - separar os comandos de cada sessão facilita a auditoria.

# Convert /dev/nnn/X or /dev/nnnX to "nnnX"
HISTSUFFIX=`tty | sed 's/\///g;s/^dev//g'`
# History file is now .bash_history_pts0
HISTFILE=".bash_history_$HISTSUFFIX"
HISTTIMEFORMAT="%y-%m-%d %H:%M:%S "
HISTCONTROL=ignoredups:ignorespace
shopt -s histappend
HISTSIZE=1000
HISTFILESIZE=5000

A história agora se parece com:

user@host:~# test 123
user@host:~# test 5451
user@host:~# history
1  15-08-11 10:09:58 test 123
2  15-08-11 10:10:00 test 5451
3  15-08-11 10:10:02 history

Com os arquivos parecidos com:

user@host:~# ls -la .bash*
-rw------- 1 root root  4275 Aug 11 09:42 .bash_history_pts0
-rw------- 1 root root    75 Aug 11 09:49 .bash_history_pts1
-rw-r--r-- 1 root root  3120 Aug 11 10:09 .bashrc
Litch
fonte
3

Aqui vou apontar um problema com

export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"

e

PROMPT_COMMAND="$PROMPT_COMMAND;history -a; history -n"

Se você executar o source ~ / .bashrc, o $ PROMPT_COMMAND será como

"history -a; history -c; history -r history -a; history -c; history -r"

e

"history -a; history -n history -a; history -n"

Essa repetição ocorre sempre que você executa 'source ~ / .bashrc'. Você pode verificar PROMPT_COMMAND após cada vez que executar 'source ~ / .bashrc' executando 'echo $ PROMPT_COMMAND'.

Você pode ver alguns comandos aparentemente quebrados: "history -n history -a". Mas a boa notícia é que ele ainda funciona, porque outras partes ainda formam uma sequência de comandos válida (apenas envolve algum custo extra devido à execução de alguns comandos repetidamente. E não tão limpo.)

Pessoalmente, uso a seguinte versão simples:

shopt -s histappend
PROMPT_COMMAND="history -a; history -c; history -r"

que possui a maioria das funcionalidades, embora não exista esse problema como mencionado acima.

Outro ponto a destacar é: não há realmente nada de mágico . PROMPT_COMMAND é apenas uma variável de ambiente simples do bash. Os comandos nele são executados antes de você receber o prompt do bash (o sinal $). Por exemplo, seu PROMPT_COMMAND é "eco 123" e você executa "ls" no seu terminal. O efeito é como executar "ls; eco 123".

$ PROMPT_COMMAND="echo 123"

output (Assim como executar 'PROMPT_COMMAND = "eco 123"; $ PROMPT_COMMAND'):

123

Execute o seguinte:

$ echo 3

resultado:

3
123

"history -a" é usado para escrever os comandos history na memória para ~ / .bash_history

"history -c" é usado para limpar os comandos de histórico na memória

"history -r" é usado para ler comandos de histórico de ~ / .bash_history na memória

Veja a explicação do comando history aqui: http://ss64.com/bash/history.html

PS: Como outros usuários apontaram, a exportação é desnecessária. Consulte: usando exportação em .bashrc

fstang
fonte
2

Eu escrevi um script para definir um arquivo de histórico por sessão ou tarefa com base no seguinte.

        # write existing history to the old file
        history -a

        # set new historyfile
        export HISTFILE="$1"
        export HISET=$1

        # touch the new file to make sure it exists
        touch $HISTFILE
        # load new history file
        history -r $HISTFILE

Não é necessário salvar todos os comandos do histórico, mas salva os que mais me interessam e é mais fácil recuperá-los do que passar por todos os comandos. Minha versão também lista todos os arquivos de histórico e fornece a capacidade de pesquisar por todos eles.

Fonte completa: https://github.com/simotek/scripts-config/blob/master/hiset.sh

simotek
fonte
2

Aqui está uma solução que não mistura histórias de sessões individuais!

Basicamente, é necessário armazenar o histórico de cada sessão separadamente e recriá-lo a cada prompt. Sim, ele usa mais recursos, mas não é tão lento quanto parece - o atraso começa a ser perceptível apenas se você tiver mais de 100000 entradas no histórico.

Aqui está a lógica principal:

# on every prompt, save new history to dedicated file and recreate full history
# by reading all files, always keeping history from current session on top.
update_history () {
  history -a ${HISTFILE}.$$
  history -c
  history -r
  for f in `ls ${HISTFILE}.[0-9]* | grep -v "${HISTFILE}.$$\$"`; do
    history -r $f
  done
  history -r "${HISTFILE}.$$"
}
export PROMPT_COMMAND='update_history'

# merge session history into main history file on bash exit
merge_session_history () {
  cat ${HISTFILE}.$$ >> $HISTFILE
  rm ${HISTFILE}.$$
}
trap merge_session_history EXIT

Consulte esta lista para obter uma solução completa, incluindo algumas salvaguardas e otimizações de desempenho.

Jan Warchoł
fonte
1

Isso funciona para o ZSH

##############################################################################
# History Configuration for ZSH
##############################################################################
HISTSIZE=10000               #How many lines of history to keep in memory
HISTFILE=~/.zsh_history     #Where to save history to disk
SAVEHIST=10000               #Number of history entries to save to disk
#HISTDUP=erase               #Erase duplicates in the history file
setopt    appendhistory     #Append history to the history file (no overwriting)
setopt    sharehistory      #Share history across terminals
setopt    incappendhistory  #Immediately append to the history file, not just when a term is killed
Mulki
fonte
infelizmente, a questão é estritamente para :-) festa
Jaleks
1
seu primeiro resultado no Google quando eu procurar zsh bem ... Pensei que poderia ajudar
Mulki
3
Você deve fazer uma nova pergunta, ~ "Preservar o histórico do zsh em várias janelas de terminal", supondo que ainda não exista. Está perfeitamente bem - mesmo encorajado - responder sua própria pergunta, se for uma boa pergunta.
Oli
1

Eu desejava isso há muito tempo, especialmente a capacidade de recuperar um comando por onde ele foi executado para executar novamente em um novo projeto (ou encontrar um diretório por um comando). Por isso , montei essa ferramenta , que combina soluções anteriores para armazenar um histórico global da CLI com uma ferramenta de grepping interativa chamada percol (mapeada para C ^ R). Ainda está bom na primeira máquina que comecei a usá-la, agora com um histórico de CLI com mais de 2 anos.

Ele não mexe com o histórico da CLI local no que diz respeito às teclas de seta, mas permite acessar o histórico global com bastante facilidade (que você também pode mapear para algo diferente de C ^ R)

Gordon Wells
fonte
isto é para zsh?
sjas 17/03
1
Sim, eu fiz para o zsh inicialmente. Entendi trabalhando para bash e peixe também. Deixe-me saber se funciona ou não. Eu não mudei isso há um tempo e não tenho certeza do quão claro estive em minhas instruções de instalação
Gordon Wells
1

Porque eu prefiro uma história infinita que foi salva em um arquivo personalizado. Eu crio essa configuração com base em https://stackoverflow.com/a/19533853/4632019 :

export HISTFILESIZE=
export HISTSIZE=
export HISTTIMEFORMAT="[%F %T] "

export HISTFILE=~/.bash_myhistory
PROMPT_COMMAND="history -a; history -r; $PROMPT_COMMAND"
Eugen Konkov
fonte
-1

Aqui está o trecho do meu .bashrc e breves explicações sempre que necessário:

# The following line ensures that history logs screen commands as well
shopt -s histappend

# This line makes the history file to be rewritten and reread at each bash prompt
PROMPT_COMMAND="$PROMPT_COMMAND;history -a; history -n"
# Have lots of history
HISTSIZE=100000         # remember the last 100000 commands
HISTFILESIZE=100000     # start truncating commands after 100000 lines
HISTCONTROL=ignoreboth  # ignoreboth is shorthand for ignorespace and     ignoredups

HISTFILESIZE e HISTSIZE são preferências pessoais e você pode alterá-las conforme seu gosto.

Hopping Bunny
fonte