Comportamento estranho do histórico do bash ao executar várias sessões

15

Como o histórico da linha de comando é armazenado quando uso várias janelas de terminal? Sei que ele está armazenado, .bash_historymas não consigo ver a lógica de qual histórico é usado se abrir uma nova janela. Parece quase não-determinístico, no sentido de que nunca sei qual comando vou ver se tentar usar a seta em uma nova janela.

Alguém pode explicar isso?

Existe uma maneira de controlar o histórico de maneira que eu possa reutilizá-lo a partir de uma janela específica?

Alex Gitelman
fonte

Respostas:

14

Para entender o comportamento do histórico do bash, primeiro você precisa saber o seguinte:

  1. Há o histórico no arquivo de histórico.
  2. Existe a história na memória de um processo do bash.
  3. O histórico na memória de um processo do bash não é sincronizado com o histórico na memória de qualquer outro processo do bash.
  4. O histórico na memória de um processo do bash não é sincronizado com o histórico no arquivo, a menos que seja explicitamente solicitado ou durante algum evento específico (veja abaixo).

Usando as configurações padrão, o ciclo de vida de uma sessão do bash com relação ao histórico é o seguinte:

  1. Durante a inicialização, o bash lerá o arquivo de histórico. O conteúdo do arquivo histórico agora está na memória do processo do bash.
  2. Durante o uso normal, apenas o histórico da memória é manipulado.
  3. Durante o desligamento, o histórico na memória é gravado no arquivo de histórico, substituindo qualquer conteúdo anterior do arquivo de histórico.

O comportamento aparentemente não determinístico que você observou é principalmente porque o conteúdo do arquivo de histórico é sempre o histórico da última sessão fechada do bash, e o bash apenas lê o arquivo do histórico durante a inicialização.

Leia o manual do bash para obter uma explicação mais detalhada do processo de inicialização e desligamento.

Observe que, com as configurações padrão, quero dizer as configurações padrão do bash. Sua distribuição pode ter fornecido um .bashrc(ou /etc/bash.bashrc) que altera esse comportamento.

Ao ativar a opção de shell, histappendvocê pode pedir ao bash para anexar em vez de substituir o arquivo de histórico. Você pode ativar histappendusando o comando shopt -s histappend. Para ter essa opção sempre ativada, você deve colocar o comando no seu .bashrc(ou outro arquivo de inicialização). Leia mais sobre o shoptcomando no manual do bash

Observe que a habilitação histappendnão reduzirá muito o comportamento aparentemente não determinístico. Isso ocorre porque cada sessão do bash ainda tem seu próprio histórico na memória. É possível ter um histórico do bash principalmente sincronizado. Há um guia sobre como fazer com que cada processo do bash tenha um histórico sincronizado principalmente em um encadeamento no estouro de pilha .

usando o comando interno, historyvocê pode dizer explicitamente ao bash para ler o histórico de arquivo para a memória ou para gravar da memória para o arquivo. Por exemplo: history -rirá ler o conteúdo do arquivo e anexá-lo ao histórico na memória. history -wgravará o histórico atual da memória para o arquivo, substituindo o conteúdo anterior. Isso é basicamente o que acontece durante o desligamento. Leia mais sobre o historycomando no manual do bash

Para completar, aqui está uma lista das variáveis ​​internas que modificam o comportamento do histórico:

  • HISTFILE: o arquivo para ler e escrever o histórico.
  • HISTFILESIZE: a contagem máxima de linhas para o arquivo de histórico.
  • HISTSIZE: a contagem máxima de linhas para o histórico na memória.
  • HISTCONTROL, HISTIGNORE, HISTTIMEFORMAT: Não é relevante para esta discussão. Leia o manual do bash para obter detalhes.
lesmana
fonte
Boa explicação. Você mencionou o desligamento, mas e quanto a matar a sessão do terminal? A sessão pode ser interrompida via logout ou interface do usuário ou por outros meios, como queda na conexão de rede. Se o arquivo de histórico inteiro for substituído e você tiver várias sessões, você está dizendo que o histórico do último fechado será usado no arquivo de histórico? Isso poderia explicar o comportamento não determinístico.
precisa
o ponto do ciclo de vida (3) não está correto. Parece que apenas a primeira sessão do bash será gravada no arquivo de histórico. Teste: abra 2 sessões na ordem a, b. Faça 'eco Olá' em b . Então saia em b . Em seguida, abra uma nova sessão c . Esta sessão não terá eco olá em sua história.
user606723
@ AlexGitelman: se um processo bash for eliminado, ele não terá a chance de sobrescrever o arquivo de histórico. e sim, o histórico da última sessão fechada é o que estará no arquivo de histórico.
Lesmana
@ user606723: o ponto 3 está correto. leia o manual do bash. experimente novamente usando um .bashrcarquivo mínimo . observe que sua distribuição pode ter alterado algumas configurações em /etc/bash.bashrc. verifique especificamente a opção de shell histappend.
Lesmana
0

AFAIK, os comandos bash são salvos após o término da sessão SSH. Portanto, os comandos não são salvos quando uma sessão termina de forma anormal (por exemplo, devido a falha na rede). Eu estou falando aqui sobre sessões SSH. Os terminais locais podem usar uma abordagem semelhante.

Ao abrir várias sessões ao mesmo tempo, os comandos digitados em uma sessão não são vistos na outra enquanto ambos estão ativos. No entanto, você verá esses comandos quando encerrar sua sessão, reabra-a.

Khaled
fonte
Este não é o comportamento que experimentei. Posso confirmar isso fazendo um teste rápido em que abro uma sessão ssh, faço um comando e faço uma saída normal. Nesse caso, eu tive outra sessão ssh anteriormente ativa. Nesta sessão bash pré-existente, verifico .bash_history e não encontro nada gravado. Acho que a primeira sessão do bash em execução é a única que acaba gravando em .bash_history.
user606723
O encerramento da sua sessão não afetará as sessões em execução no momento, mas as novas sessões!
Khaled
E se não for o SSH, mas a janela do terminal do Gnome que eu fecho pela interface do usuário?
precisa
Ele precisa ser verificado. Atualmente, não tenho acesso a um terminal Gnome!
Khaled
@Khaled, testou, não afeta novas sessões. (Eu verifiquei .bash_history antes de qualquer forma, que é onde o bash recebe o histórico de comandos para novas sessões, eu então sabia que não iria; t trabalho, mas eu humour'ed você de qualquer maneira.)
user606723