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
ls
em um, alterne para outro terminal já em execução e pressione,ls
aparece) - 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?
bash
command-history
Oli
fonte
fonte
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.Respostas:
Adicione o seguinte ao ~ / .bashrc
fonte
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 dehistory -<option>
comandos que funciona com aHISTCONTROL=ignoredups:erasedups
configuração.export
as variáveisHISTCONTROL
ePROMPT_COMMAND
: você as define.bashrc
para que elas sejam definidas em todos os shell (mesmo nos não interativos, o que também é um desperdício).Então, isso é tudo relacionado à história
.bashrc
:Testado com o bash 3.2.17 no Mac OS X 10.5, o bash 4.1.7 no 10.6.
fonte
sleep 9999
e (sem esperar o término do sono) na janela de shell B, quero poder versleep 9999
no histórico do bash.href
que 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
export
as variáveis: você está definindo-os em.bashrc
que eles serão definidos em cada shell (mesmo nas não-interativas, o que representa um desperdício)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
!number
funcione (com algumas restrições).Usando o Bash versão 4.1.5 no Ubuntu 10.04 LTS (Lucid Lynx).
Explicação:
Anexe a linha recém-inserida ao
$HISTFILE
(o padrão é.bash_history
). Isso fará$HISTFILE
crescer uma linha.Definir a variável especial
$HISTFILESIZE
com algum valor fará com que o Bash trunque$HISTFILE
não exceda as$HISTFILESIZE
linhas removendo as entradas mais antigas.Limpe o histórico da sessão em execução. Isso reduzirá o contador de histórico pela quantidade de
$HISTSIZE
.Leia o conteúdo
$HISTFILE
e 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$HISTFILE
não é necessariamente$HISTFILESIZE
.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$HISTFILE
seja exatamente$HISTSIZE
(isso significa que$HISTFILESIZE
deve 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
Eu recomendo usar as seguintes opções do Bash.
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:
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 umCTRL+C
prompt. Costumo usarCTRL+C
para descartar uma longa linha de comando quando decido que não quero executar essa linha. Às vezes, tenho que usarCTRL+C
para 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.
fonte
history -n
porque isso atrapalha o contador de histórico. Além disso, eu acheihistory -n
muito confiável.history -a
, sem-c
e-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.Eu não estou ciente de nenhuma maneira de usar
bash
. Mas é um dos recursos mais populares dozsh
.Pessoalmente, prefiro
zsh
mais,bash
então recomendo tentar.Aqui está a parte do meu
.zshrc
que lida com a história:fonte
Para fazer isso, você precisará adicionar duas linhas ao seu
~/.bashrc
:De
man bash
:fonte
Você pode editar seu prompt do BASH para executar os "history -a" e "history -r" que Muerr sugeriu:
(no caso de você estragar alguma coisa, o que é quase garantido)
(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:
Fiz testes básicos para garantir que funcione, mas não consigo falar com nenhum efeito colateral ao executar
history -a;history -r
em todos os prompt.fonte
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 9999
e (sem esperar o término do sono) na janela de shell B, quero poder versleep 9999
no 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_COMMAND
ouPS1
, sendo que as duas estão sendo executadas tarde demais, somente após a conclusão dosleep 9999
comando.fonte
Você pode usar
history -a
para anexar o histórico da sessão atual ao arquivo de histórico e, em seguida, usarhistory -r
nos outros terminais para ler o arquivo de histórico.fonte
Certo, então finalmente isso me incomodou em encontrar uma solução decente:
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:
(Exemplo simplificado)
E em outro:
De jeito nenhum eu gostaria que o comando fosse compartilhado
fonte
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:
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:
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.
fonte
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.
fonte
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.
fonte
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.
A história agora se parece com:
Com os arquivos parecidos com:
fonte
Aqui vou apontar um problema com
e
Se você executar o source ~ / .bashrc, o $ PROMPT_COMMAND será como
e
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:
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".
output (Assim como executar 'PROMPT_COMMAND = "eco 123"; $ PROMPT_COMMAND'):
Execute o seguinte:
resultado:
"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
fonte
Eu escrevi um script para definir um arquivo de histórico por sessão ou tarefa com base no seguinte.
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
fonte
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:
Consulte esta lista para obter uma solução completa, incluindo algumas salvaguardas e otimizações de desempenho.
fonte
Isso funciona para o ZSH
fonte
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)
fonte
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 :
fonte
Aqui está o trecho do meu .bashrc e breves explicações sempre que necessário:
HISTFILESIZE e HISTSIZE são preferências pessoais e você pode alterá-las conforme seu gosto.
fonte