Como fazer com que o histórico da linha de comando se aplique a todos os terminais

4

Eu sempre tenho pelo menos 3 janelas de terminador (um programa de terminal) abertas, mas às vezes abro outro terminal para fazer algo rapidamente. Como posso fazer com que o histórico de comandos seja comum em todos eles?

    
por Scott Goodgame 25.06.2013 / 10:48

1 resposta

3

Graças ao link fornecido por gertvdijk acima, estou postando minha solução favorita.

Aqui está minha tentativa de compartilhar o histórico da sessão do Bash. Isso permitirá o compartilhamento de histórico entre as sessões do bash de forma que o contador de histórico não seja misturado e a expansão do histórico como! Number funcionará 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

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

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

PROMPT_COMMAND=_bash_history_sync

Explicação: A função history () 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 depois).

Anexe a linha que acabou de ser inserida ao $ HISTFILE (o padrão é .bash_history). Isso fará com que $ HISTFILE cresça em uma linha.

Definir a variável especial $ HISTFILESIZE para algum valor fará com que o Bash trunque $ HISTFILE para não exceder as linhas $ HISTFILESIZE 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 de $ HISTFILE e insira-os no histórico atual da sessão em execução. Isso aumentará o contador de histórico pela quantidade de linhas em $ HISTFILE. Observe que a contagem de linhas de $ HISTFILE não é necessariamente $ HISTFILESIZE.

Mais explicações: A etapa 1 garante que o comando da sessão em execuçã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 da sessão atual.

Como o passo 4 vai levantar o contador de histórico, precisamos reduzir o contador de alguma forma. Isso é feito no passo 3.

No passo 3, o contador de histórico é reduzido em $ HISTSIZE. Na etapa 4, o contador de histórico é gerado 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 que $ HISTSIZE).

Sobre as restrições da expansão do histórico: Geralmente, uma vez que você tenha mais de uma sessão de Bash, não há garantia de que uma expansão de histórico por número manterá seu valor entre duas exibições de prompt do Bash. Toda vez que PROMPT_COMMAND é executado, algum comando de outra sessão de Bash pode entrar no seu histórico de sessão atual e, em seguida, os números do histórico serão diferentes. Isso significa que você sempre precisa procurar o número imediatamente antes de usá-lo. Eu acho essa restrição razoável. Eu tenho que procurar o número todas as vezes, porque não consigo me lembrar de números de histórico arbitrários.

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 de Bash.

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

Erros estranhos: Executar o comando history canalizado para qualquer coisa resultará em que o comando seja listado no histórico duas vezes. Por exemplo:

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

Todos serão listados no histórico duas vezes. Não faço ideia do porquê.

Idéias para melhorias: Modifique a função _bash_history_sync () para que não seja executada toda vez. Por exemplo, não deve executar após um CTRL + C no prompt. Costumo usar CTRL + C para descartar uma linha de comando longa quando decido que não quero executar essa linha. Às vezes eu tenho que usar CTRL + C para parar 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 dado número de histórico mantém seu valor para entradas de histórico desta sessão.

    
por Scott Goodgame 25.06.2013 / 12:14