Como obter o histórico compartilhado entre guias diferentes

19

Usei a resposta em /unix//a/1292/41729 para ativar o histórico compartilhado em tempo real entre terminais bash separados. Conforme explicado na resposta acima, isso é alcançado adicionando:

# avoid duplicates..
export HISTCONTROL=ignoredups:erasedups  
# append history entries..
shopt -s histappend

# After each command, save and reload history
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

Isso funciona bem se os shells do bash estiverem separados (por exemplo, abrir diferentes terminais do bash usando CTRL+ALT+T. No entanto, não funcionará se eu usar tabs(a partir de um terminal aberto `CTRL + SHIFT + T) em vez de novas janelas. Por que essa diferença de comportamento? posso compartilhar o histórico do bash também entre várias guias?

ATUALIZAÇÃO: Percebi um comportamento incomum: se eu digitar CTRL+C, o último comando digitado em qualquer um dos outros terminais (uma guia ou não) será exibido corretamente. É como se CTRL + C force uma descarga do histórico para que seja compartilhada corretamente.

Como exemplo, as saídas (T1 denota o terminal 1 e o terminal 2 do T2):

T1:
ls -lah <enter>
# the list of files and directory is shown

T2:
cd Documents <enter>

T1:
<up> (i.e. I press the up arrow)
ls -lah #i.e the last command in terminal 1 is shown rather than the last of terminal 2
^C (i.e. I press CTRL+C)
<up>
cd Documents #the last command issued in terminal 2 is correctly displayed

Espero que isso possa oferecer alguma dica!

lucacerona
fonte
Você adicionou isso ao seu ~.bashrcarquivo? Em uma nota lateral, exportar essas variáveis ​​é inútil; apenas desperdiça espaço no ambiente.
geirha
@geirha sim, eu adicionei ao meu arquivo .bashrc. Obrigado pelo comentário sobre a exportação.
lucacerone

Respostas:

2

Parece que você está tentando acessar o histórico do outro terminal antes da sincronização. PROMPT_COMMANDé executado imediatamente antes da impressão de um novo prompt, ou seja, depois de executar um comando e antes de digitar o próximo comando. Portanto, isso não acontecerá imediatamente em T1; você precisa fazer com que um novo prompt seja exibido.

Para testar isso, tente esta variante em suas etapas (adicionei um extra <enter>no T1):

T1:
ls -lah <enter>
# the list of files and directory is shown

T2:
cd Documents <enter>

T1:
<enter>
<up> (i.e. I press the up arrow)

Com esse pressionamento extra de enter, você recebe um novo prompt, que executa PROMPT_COMMANDe sincroniza seu histórico, e, portanto, espero que essa seta para cima recupere o em cdvez de ls, como você queria. Infelizmente, não acho que exista uma maneira de fazer a sincronização instantaneamente em todos os terminais sem executar nenhum comando que você queira; efetivamente, isso exigiria que todas as suas sessões de login sincronizassem suas listas de histórico continuamente o tempo todo, o que seria um enorme desperdício de CPU e taxa de transferência de disco.

Paulo
fonte
você está certo, pressionando enter, ele é sincronizado depois. Mesmo se houver uma perda de memória ou CPU como eu poderia forçar a sincronização (se é demais Eu sempre pode desativá-lo, mas eu gostaria de dar-lhe uma tentativa)?
lucacerone
1

Eu fiz a mesma pergunta e aqui está a resposta que eu vim com ....

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
Scott Goodgame
fonte
dois esclarecimentos antes de tentar: devo remover as outras opções de histórico, então? isso entra no .bashrc certo?
Lucacerone
infelizmente ele não funciona ...
lucacerone
Cada vez que HISTFILESIZEé alterado, ele tenta automaticamente truncar o arquivo de histórico existente. A mudança HISTSIZEtem um efeito semelhante no histórico atual. Para referência, consulte o comentário no variables.cbash src logo antes sv_histsize.
18715 Brian Brian Gandhi
1

adicione essas linhas ao seu .bashrcarquivo

# avoid duplicates..
export HISTCONTROL=ignoredups:erasedups  
# append history entries..
shopt -s histappend

trap 'history -r' USR1 
export PROMPT_COMMAND="history -a ; history -c; ps a | awk '/ bash$/ {system (\"kill -USR1 \" \$1)}'; $PROMPT_COMMAND"

Nota:

Inicialmente, eu fiz meu teste enviando sinal USR1 para bater com killall, depois pensei em usar um nome de shell exclusivo, uma cópia de bash chamada testshell, para evitar matar meus próprios shells que poderiam ser executados (processos cron, por exemplo), mas estranhamente isso não era possível. trabalhando.

O killall não era seletivo o suficiente, substituí-o por um script que mata apenas os processos do bash em um tty ( ps arelata apenas processos vinculados a um tty)

Não se esqueça de reiniciar sua sessão para ter um novo PROMPT_COMMAND, quando eu estava testando, vi muitos dos meus testes anteriores empilhados dentro de PROMPT_COMMAND.

Emmanuel
fonte
Você não precisa do novo usuário e do outro shell, basta dizer killallpara enviar o sinal apenas para processos do mesmo usuário com um -uargumento adicional , e.g. -u $ (whoami) `.
Philipp Wendler
Eu acho que a sintaxe do csh está errada ... @PhilippWendler, você poderia elaborar um pouco?
Lucacerone
A questão é sobre o bash, então usei a sintaxe do bash. Eu não sei csh. Para o bash, killall -q -USR1 -u $(whoami) bashenvia o sinal USR1 para todos os processos do bash do usuário atual.
Philipp Wendler
@ Philipp ty btw Eu não testei a solução shell dedicada, era para corrigir um caso em que o script cron bash seria executado.
Emmanuel
@LucaCerone eu reescrevi parece funcionar
Emmanuel
0

Eu tive o mesmo comportamento estranho em Yakuake quando tentei criar um prompt de bash elaborado que mostraria o número de outros logins. O número não aumentou para guias. Minha solução alternativa foi dizer ao Yakuake para executar bashnovamente em cada nova guia, iniciando basicamente o bash no bash. Começou a funcionar perfeitamente. Pode ser que também o ajudasse. Meu palpite cego é que a GUI do console carrega o bash e se alimenta das instâncias do bash. Pode ser que seja capaz de mexer com eles.

Barafu Albino
fonte
Eu tentei carregar bash no bash, mas sem sucesso :(
lucacerone 26/06