Por que o bash_history sempre aparece da mesma forma e não é atualizado usando shells que não são de login?

5

Os últimos dias tenho notado que sempre que eu desligar meu sistema (Debian Testing) e iniciar uma sessão de bash, em seguida, pressione a tecla de seta para cima, recebo os comandos da primeira vez que limpei o cache de histórico usando% código%. Não tenho certeza de como isso aconteceu, mas mesmo se eu limpar meu histórico novamente, então pressione a seta para cima, legal funciona, mas se eu iniciar outro shell não (ainda menos sempre que eu reiniciar, desligar ou fazer logoff) .

Eu já tentei de tudo (até mesmo excluir o history -c manualmente), então fiquei sem ideias.

$ echo $SHELL
/bin/bash
$ /bin/bash --version
GNU bash, version 4.2.45(1)-release (i486-pc-linux-gnu)
$ echo $HISTFILE
/home/braiam/.bash_history

Ao procurar informações para adicionar a pergunta, eu corri .bash_history (para não parecer um idiota) e encontrei o problema:

$ ls -l .bash_history 
-r--------. 1 braiam braiam 59372 Jul 26 20:18 .bash_history

Mas a execução de ls -l .bash_history não salvou o dia. Agora eu me pergunto como isso poderia acabar assim ...

Após excluir o arquivo chmod +w .bash_history , não tenho histórico. Eu verifiquei o .bashrc para pistas:

cat .bashrc | grep -i hist
# don't put duplicate lines or lines starting with space in the history.
HISTCONTROL=ignoreboth
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000

Seguindo a resposta de ash, em um shell sem login (gnome-terminal):

braiam@bt:~$ echo abacaba; echo $$
abacaba
15372
braiam@bt:~$ 

Em seguida, acionou outro shell de não-login:

braiam@bt:~$ strace -o e -s 256 -p 15372
Process 15372 attached - interrupt to quit

Voltou ao primeiro shell e, em seguida, digite .bash_history :

braiam@bt:~$ echo abacaba; echo $$
abacaba
15372
braiam@bt:~$ history -a
braiam@bt:~$ 

No shell com strace, nada:

braiam@bt:~$ strace -o e -s 256 -p 15372
Process 15372 attached - interrupt to quit

Aqui eu estava quase sem esperança, então decidi olhar o strace manual e descobri que history -a é despejar o resultado em um arquivo, então -o restaura isso:

cat e
read(0, "", 1)                       = 1
read(0, "[", 1)                         = 1
read(0, "A", 1)                         = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "history -w", 10)              = 10
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
read(0, "", 1)                       = 1
read(0, "[", 1)                         = 1
read(0, "A", 1)                         = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "a", 2)                     = 2
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
read(0, "\r", 1)                        = 1
write(2, "\n", 1)                       = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigaction(SIGINT, {0x80a0e30, [], 0}, {0x80e9d00, [], 0}, 8) = 0
rt_sigaction(SIGTERM, {SIG_IGN, [], 0}, {SIG_IGN, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {SIG_IGN, [], 0}, {SIG_IGN, [], 0}, 8) = 0
rt_sigaction(SIGALRM, {0x80a1080, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 0}, {0x80e9d00, [], 0}, 8) = 0
rt_sigaction(SIGTSTP, {SIG_IGN, [], 0}, {SIG_IGN, [], 0}, 8) = 0
rt_sigaction(SIGTTOU, {SIG_IGN, [], 0}, {SIG_IGN, [], 0}, 8) = 0
rt_sigaction(SIGTTIN, {SIG_IGN, [], 0}, {SIG_IGN, [], 0}, 8) = 0
rt_sigaction(SIGWINCH, {0x80a09e0, [], 0}, {0x80e9550, [], SA_RESTART}, 8) = 0
rt_sigaction(SIGINT, {0x80a0e30, [], 0}, {0x80a0e30, [], 0}, 8) = 0
time(NULL)                              = 1378047084
stat64("/home/braiam/.bash_history", {st_mode=S_IFREG|0600, st_size=44, ...}) = 0
open("/home/braiam/.bash_history", O_WRONLY|O_APPEND|O_LARGEFILE) = 3
write(3, "history -w\nhistory -a\n", 22) = 22
close(3)                                = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
rt_sigaction(SIGINT, {0x80a0e30, [], 0}, {0x80a0e30, [], 0}, 8) = 0
time(NULL)                              = 1378047084
rt_sigprocmask(SIG_BLOCK, [CHLD TSTP TTIN TTOU], [], 8) = 0
ioctl(255, TIOCSPGRP, [15372])          = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigaction(SIGINT, {0x80a0e30, [], 0}, {0x80a0e30, [], 0}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
ioctl(0, TIOCGWINSZ, {ws_row=24, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(0, TIOCSWINSZ, {ws_row=24, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT QUIT ALRM TERM TSTP TTIN TTOU], [], 8) = 0
rt_sigaction(SIGINT, {0x80e9d00, [], 0}, {0x80a0e30, [], 0}, 8) = 0
rt_sigaction(SIGTERM, {0x80e9d00, [], 0}, {SIG_IGN, [], 0}, 8) = 0
rt_sigaction(SIGTERM, {SIG_IGN, [], 0}, {0x80e9d00, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {0x80e9d00, [], 0}, {SIG_IGN, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {SIG_IGN, [], 0}, {0x80e9d00, [], 0}, 8) = 0
rt_sigaction(SIGALRM, {0x80e9d00, [], 0}, {0x80a1080, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 0}, 8) = 0
rt_sigaction(SIGTSTP, {0x80e9d00, [], 0}, {SIG_IGN, [], 0}, 8) = 0
rt_sigaction(SIGTSTP, {SIG_IGN, [], 0}, {0x80e9d00, [], 0}, 8) = 0
rt_sigaction(SIGTTOU, {0x80e9d00, [], 0}, {SIG_IGN, [], 0}, 8) = 0
rt_sigaction(SIGTTOU, {SIG_IGN, [], 0}, {0x80e9d00, [], 0}, 8) = 0
rt_sigaction(SIGTTIN, {0x80e9d00, [], 0}, {SIG_IGN, [], 0}, 8) = 0
rt_sigaction(SIGTTIN, {SIG_IGN, [], 0}, {0x80e9d00, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigaction(SIGWINCH, {0x80e9550, [], SA_RESTART}, {0x80a09e0, [], 0}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "]0;braiam@bt: ~[01;31mbraiam@bt[00m:[01;34m~[00m$ ", 56) = 56
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
read(0,  <unfinished ...>

Então, de acordo com isso, não há problema. Em seguida, eu abro outro shell de não-login e sem alegria. O histórico não está carregado. Um cat e revela que o arquivo foi realmente preenchido, mas o shell não-login não o aceita.

Agora, tentei os dois cat .bash_history aqui (muito longo para o limite de caracteres) e strace -o /tmp/e -s 512 bash aqui (ambos de pastebin.com, desculpe). Aqui com as configurações originais (menos a permissão -w em .bash_history).

Eu tentei o login em seguida, Ctrl + Alt + F1, logado, pressionei a seta para cima, cruzei os dedos e funcionou! Mas, isso ainda me deixa com o interrogador, por que o shell não-login não carrega o histórico?

    
por Braiam 31.08.2013 / 18:09

4 respostas

3

você tentou history -c && history -w ?

history -c limpa o cache da função history e history -w escreve os comandos no cache da função history (nothing) em .bash_history.

Outra opção é limpar o histórico bash /dev/null > ~/.bash_history e vincular ~/.bash_history a /dev/null : ln -sf /dev/null ~/.bash_history

se você não quiser salvar os comandos da sessão de shell atual, deverá executar history -r para redefinir o cache de histórico para seu estado inicial (antes de iniciar a sessão). Então você efetua logout e os comandos no cache do histórico (o mesmo que antes de iniciar a sessão do shell) serão gravados em .bash_history

    
por 31.08.2013 / 18:18
3

Um dos motivos pelos quais isso pode acontecer é que os shells não estão saindo normalmente ou você está procurando por atualizações quando os shells ainda estão sendo executados.

Para testar esse cenário, tente history -a após algum comando exclusivo, como echo abacaba em um shell em execução e, em seguida, inicie um novo shell. Se o novo shell obtiver as atualizações do primeiro, então escrever e ler o arquivo de histórico está funcionando. No entanto, se isso não funcionar, algo está errado, e eu pessoalmente usaria strace na tentativa de diagnosticar.

Outra coisa a verificar é que a variável HOME não foi alterada e está definida para o mesmo caminho definido no arquivo passwd para o usuário.

Usando strace para diagnosticar

  • em um shell, echo abacaba; echo $$
  • em outro shell, strace -o e -s 256 -p $PID , onde $PID = $$ de saída do primeiro shell
  • no primeiro shell, history -a
  • interrompa a strace e examine-a para o processamento de history -a ; deve haver chamadas open () e write ().

Shells não interativos

É estranho que os shells não interativos não estejam obtendo o histórico do shell, mas isso pode ser explicado por várias coisas. Mais diagnósticos ajudarão.

O Strace pode ser usado novamente para ajudar nesse fim, se a inicialização dos shells não interativos puder ser modificada para inserir strace. Por exemplo, o seguinte mostra um comando de inicialização do shell modificado para usar strace:

bash /home/jack/bin/jacks_script
strace -f -o /tmp/e -s 512 bash /home/jack/bin/jacks_script

É claro que, se mais de uma dessas execuções por vez, /tmp/e será sobrescrito.

Usando grep open /tmp/e , o caminho completo para o arquivo bash_history deve aparecer se o shell estiver carregado. Portanto, esse comando permite duas verificações: (1) que um arquivo de histórico está sendo aberto e lido e (2) que o caminho para o arquivo de histórico é conforme esperado.

Sem strace

Verifique se o shell tem o conjunto de opções history ( set -o history for bash).

Uma coisa que não está clara é quando HISTFILE é verificado pelo shell. Por exemplo, se estiver definido no .bash_profile , não tenho certeza se ele afetará a leitura do histórico do shell, porque é depois que o shell é iniciado, mas antes que o primeiro prompt de comando seja fornecido ao usuário.

    
por 31.08.2013 / 21:12
1

Você pode apenas desmarcar $HISTFILE (que contém o caminho para o arquivo de histórico), o que não afetará sua capacidade de usar o histórico na sessão atual:

unset HISTFILE
    
por 31.08.2013 / 18:49
1

O que acabei fazendo foi definir HISTFILESIZE como 0 no arquivo .bashrc , como Drav Sloan disse nos comentários.

[...]
HISTFILESIZE=0
[...]
    
por 31.08.2013 / 18:09