Por que o histórico não sobrescreve, mas acrescenta quando histappend está desativado no Bash?

6

Vários dias atrás, eu tinha uma guia Terminal fazendo ssh e a outra fazendo muito trabalho localmente. E então eu reiniciei a máquina (em um Mac com Mavericks).

Quando executei o Terminal novamente, descobri que todo o histórico de comandos da segunda guia não estava lá. Havia apenas o comando ssh .

Então eu pesquisei como "mesclar" o histórico de alguma forma, e descobri que precisamos fazer um shopt -s histappend no nosso arquivo ~/.bashrc para que o histórico seja anexado, em vez de "sobrescrever" - nós don ' Não quero um conjunto de histórico sobrescrevendo o outro conjunto; queremos anexar.

No entanto, quando vou para a caixa do OS X Yosemite e uso shopt , vi que histappend está desativado, mas quando abri duas guias, uma com echo abc e a outra echo def , e saiu, eu reabri o Terminal novamente e emiti um comando history , e vi os comandos echo abc e echo def .

E então eu executei o Ubuntu 2014-10 no VirtualBox e fiz coisas semelhantes, e ainda vi os dois históricos registrados (primeiro eu executei shopt -u histappend no Bash para definir a opção como primeiro desativado).

Então, qual mecanismo está fazendo isso realmente? Então histappend não tem significado, se a ativação ou desativação não importa?

Eu também comentei o shopt -s histappend no meu .bashrc e reiniciei o Terminal e tentei novamente, e vi o histórico de ambas as abas capazes de combinar ... então isso é um comportamento realmente estranho e o que pode estar causando isso? / p>     

por 太極者無極而生 29.08.2015 / 06:09

2 respostas

1

Acredito que histappend é o comportamento definido para um terminal.

Tente o seguinte em um novo terminal:

shopt -s histappend
export HISTSIZE=1
export HISTFILESIZE=500

Em seguida, feche o terminal. Você verá então como o seu arquivo de histórico tem os últimos 499 últimos comandos que ele já tinha mais " export HISTFILESIZE=50 ", que você acabou de digitar. Seu histórico foi anexado e truncado para 500.

Agora tente isso em outro novo terminal:

shopt -u histappend
export HISTIZE=1
export HISTFILESIZE=500

E novamente, feche o terminal. Você verá como agora seu terminal tem apenas um comando " export HISTFILESIZE=500 ".

O truque é que sem histappend , o arquivo de histórico é sobrescrito com o que existe atualmente no histórico de terminal (um comando).

Você não notará o seu comportamento se HISTFILE = HISTFILESIZE , mas eu acredito que não tem nada a ver com o trabalho em vários terminais, isso deve ser gerenciado por outra coisa ...

Espero que ajude!

    
por 18.06.2016 / 20:26
1

@ David Dai está correto sobre este tópico de ajuda bash.

Aqui é o código bash relevante em C.

if (history_lines_this_session <= where_history () || force_append_history)
  {
    result = append_history (history_lines_this_session, hf);
    history_lines_in_file += history_lines_this_session;
  }
else
  {
    result = write_history (hf);
    history_lines_in_file = history_lines_this_session;
  }

shopt -s histappend define force_append_history como diferente de zero ( true ).

history_lines_this_session é o número de comandos que você digitou nesta sessão bash interativa. Quando você inicia o bash pela primeira vez, ele é 0. Ele aumenta em 1 cada vez que você digita um comando que é salvo no histórico.

where_history() é um índice na lista de histórico na memória, iniciando no índice 0. Ele aponta para o próximo índice para gravar o histórico. Por exemplo, quando você tem 0 histórico, ele será o índice 0. Quando você tem 6 linhas de histórico, ele será o índice 6.

Quando você inicia pela primeira vez bash e tem histórico no HISTFILE , where_history() , mas ficará limitado a <= HISTSIZE . Portanto, where_history() tem um valor máximo de HISTSIZE .

Depois de ler o HISTFILE , where_history() aumentará, mas history_lines_this_session ainda será 0. Quando você Enter HISTSIZE + 1 número de comandos, history_lines_this_session == HISTSIZE + 1 e where_history() == HISTSIZE (porque é limitado no máximo). Nesse ponto, (history_lines_this_session <= where_history()) == false so histórico será substituído se histappend estiver desativado.

Você pode testar isso no seu bash . Se histappend estiver desativado, depois que você executar HISTSIZE + 1 número de comandos, history_lines_this_session excederá where_history() por 1 e HISTFILE será sobrescrito. Você tem que ter certeza que outros comandos não estão mexendo com seu histórico para o teste funcionar (acontece no macOS). Use os seguintes comandos para desativar os comandos que podem interferir no histórico:

trap - EXIT
PROMPT_COMMAND=
SHELL_SESSION_HISTORY=0 # for macOS only
    
por 05.03.2018 / 10:15