Histórico BASH truncado para 500 linhas em cada login

17

Por algum motivo, não consigo fazer meu sistema manter meu histórico BASH após uma reinicialização. Aqui estão as seções relevantes do meu ~/.bashrc :

shopt -s histappend
PROMPT_COMMAND='history -a; updateWindowTitle'
export HISTCONTROL=ignoredups
export HISTSIZE=9999
export HISTFILESIZE=999999
export HISTFILE="$HOME/.bash_history"

Tanto quanto eu posso dizer que são todas as opções necessárias (eu sei eu costumava ser capaz de manter o histórico em várias reinicializações sem todas essas no passado). No entanto, apesar de ter adicionado essas opções várias reinicializações atrás, ainda perdi a maior parte do meu histórico após uma reinicialização. Não está vazio, mas não possui as linhas 9999 que eu tinha antes de reinicializar.

Antes que alguém se queixe, sim, eu li essas perguntas. Eu implementei algumas de suas sugestões, conforme listado acima, o resto foi inútil ou não é relevante:

Se houver a possibilidade de haver outros comandos relevantes, você poderá ver todo o meu ~/.bashrc aqui .

Então, o que estou perdendo? Por que minha história não é salva? Se alguém achar que outro arquivo pode ser relevante, avise-me e eu o postarei. Eu verifiquei executando grep -i hist \.* no meu $HOME , o que mostrou que o único arquivo . relevante contendo a string hist ou HIST era .bashrc .

Estou executando o Linux Mint Debian Edition, o GNU bash, a versão 4.2.36 (1) -release (x86_64-pc-linux-gnu) e meu emulador de terminal favorito (caso seja relevante) é terminator .

ATUALIZAÇÃO:

Seguindo a sugestão de @mpy nos comentários, alterei meu ~/.bashrc para definir HISTFILE=~/bash_history em vez do padrão ~/.bash_history e isso parece resolver o problema de shells interativos . Os shells de login ainda exibem o mesmo comportamento, com o histórico truncado em 500 lines. No entanto, não há variáveis relacionadas HIST definidas nos arquivos relevantes:

$ for f in /etc/profile ~/.profile ~/.bash_profile ~/.bash_login; do \
   echo -ne "$f :"; echo 'grep HIST $f'; \
done
/etc/profile :
/home/terdon/.profile :grep: /home/terdon/.profile: No such file or directory
/home/terdon/.bash_profile :grep: /home/terdon/.bash_profile: No such file or directory
/home/terdon/.bash_login :grep: /home/terdon/.bash_login: No such file or directory
$ grep -r HIST /etc/profile.d/  <-- returns nothing

Então, por que definir HISTSIZE e HISTFILESIZE no ~/.bashrc não é suficiente, a menos que eu defina explicitamente o $HISTFILE como algo diferente do padrão ~/.bash_history ?

    
por terdon 29.03.2013 / 23:33

4 respostas

11

O problema realmente se resume ao comportamento diferente dos shells de login e não-login. Eu defini as variáveis que controlam o histórico no meu ~/.bahsrc . Este arquivo não é lido quando alguém inicia um shell de login, ele é lido apenas por shells interativos e não-login (de man bash ):

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.

[. . . ]

When an interactive shell that is not a login shell is started, bash reads and executes commands from ~/.bashrc, if that file exists. This may be inhibited by using the --norc option. The --rcfile file option will force bash to read and execute commands from file instead of ~/.bashrc.

Portanto, cada vez que eu fazia o login, ou baixava para um tty, ou usava o ssh, o arquivo .history estava sendo truncado porque eu não o tinha definido para o tamanho certo em ~/.profile também. Eu finalmente percebi isso e simplesmente defini as variáveis em ~/.profile onde elas pertencem , em vez de ~/.bashrc

Portanto, a razão pela qual meu ~/.history estava sendo truncado foi porque eu tinha definido apenas as variáveis HISTORY em um arquivo lido por shells interativos e não-login e, portanto, toda vez que eu executava um tipo diferente de shell, as variáveis seriam ignoradas e o arquivo seria cortado de acordo.

    
por 14.05.2014 / 02:08
8

Minha sugestão é usar outro arquivo como HISTFILE , não o padrão ~/.bash_history .

Embora eu não tenha nenhuma explicação analítica, tentarei delinear o que me levou a essa sugestão: Se você usa bash como seu shell padrão (login) e também usa X (o que é muito provável), você tem uma instância bash em execução logo após o login (gráfico):

systemd
 ...
  |-login
  |   '-bash      <<====
  |       '-slim
  |           |-X -nolisten tcp vt07 -auth /var/run/slim.auth
  |           |  '-{X}
  |           '-fluxbox
  |               '-xterm -bg black -fg white
  |                   '-bash
 ...

Acho que essa instância é um shell de login, portanto, ela não lê seu ~/.bashrc e, portanto, não sabe nada sobre a opção histappend :

man bash(1): When an interactive shell that is not a login shell is started, bash reads and executes commands from /etc/bash.bashrc and ~/.bashrc, if these files exist. (...)

Contanto que esse "shell pai" seja executado, tudo estará bem, mas após seu término (isto é, parada do sistema) ele sobrescreverá ~/.bash_history (porque esse é o valor padrão) e atrapalha seu histórico ou o filma no início do sistema para (novamente padrão) 500 linhas. (Ou talvez ambos ...)

Parece-me, também, que não é suficiente incluir a configuração do histórico em ~/.bashrc , já que isso não deveria ser uma configuração tão incomum. Eu não tenho explicação para isso.

Em relação ao seu problema, que "Os shells de login ainda exibem o mesmo comportamento", você pode tentar incluir a configuração do histórico também em ~/.bash_profile :

man bash(1): When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, (...)

Infelizmente, não posso postar uma explicação mais justificada com detalhes do meu próprio bash config, já que sou um zsh guy ...

    
por 08.04.2013 / 17:57
2

Como todas as suas configurações estão em ordem de acordo com a página do manual, e como o arquivo de histórico não é restrito por tamanho (bytes), a única explicação possível que posso imaginar. Tem a ver com como a concha morre.

De acordo com a referência online, a saída elegante (histórico salvo) ocorre somente quando o shell recebe SIGHUP. Eu não posso realmente explicar como seu sistema propaga sinais quando reiniciado, mas eu suspeito que seu shell saia com SIGKILL ou SIGPWR.

Poderia ser porque o seu WM é executado de forma assíncrona (espera) e o emulador de terminal gerado a partir do WM, onde o bash recebe um sinal de saída forçada diferente de SIGHUP. Também pode ser que o sistema operacional envie rapidamente o "kill final" para todos os processos antes que o SIGHUP inicial inicialize o shell via X - > WM - > xterm, possivelmente porque o X ou o WM demora mais para sair do que o operacional para o sistema operacional estar pronto para ser desativado.

Eu estou em águas profundas com essas coisas, mas acho que algo ao longo dessas linhas causa o comportamento errático. Eu tive esse problema antes, e o remédio mais sólido é exit no bash onde você deseja manter o histórico.

Eu notei history -a em sua pergunta e não consigo pensar em por que isso não seria suficiente para preservar o histórico.

Você pode solucionar o problema imaginando o que realmente mata o seu bash e tentar descobrir onde o sinal se origina e corrigir o problema ou simplesmente liberar o histórico quando souber qual sinal é o último (presumindo que os discos ainda estejam online até então):

trap "echo got 1  >/tmp/sig1;  exit" SIGHUP
trap "echo got 2  >/tmp/sig2;  exit" SIGINT
trap "echo got 15 >/tmp/sig15; exit" SIGTERM
 .. and so on...

A captura de tela incluída ilustra o que estou falando no segundo e terceiro parágrafos. A sequência é que eu em shell da esquerda , mato o shell esquerdo da direita e cat o histórico.

man bash

On startup, (...) The file named by the value of HISTFILE is truncated, if necessary, to contain no more than the number of lines specified by the value of HISTFILESIZE (+ default 500).

If the histappend shell option is enabled (+ default on here), the lines are appended to the history file, otherwise the history file is overwritten.

referência on-line

3.7.6 Signals

When Bash is interactive, in the absence of any traps, it ignores SIGTERM (so that ‘kill 0’ does not kill an interactive shell), and SIGINT is caught and handled (so that the wait builtin is interruptible). When Bash receives a SIGINT, it breaks out of any executing loops. In all cases, Bash ignores SIGQUIT. If job control is in effect (see Job Control), Bash ignores SIGTTIN, SIGTTOU, and SIGTSTP.

Non-builtin commands started by Bash have signal handlers set to the values inherited by the shell from its parent. When job control is not in effect, asynchronous commands ignore SIGINT and SIGQUIT in addition to these inherited handlers. Commands run as a result of command substitution ignore the keyboard-generated job control signals SIGTTIN, SIGTTOU, and SIGTSTP.

The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP. To prevent the shell from sending the SIGHUP signal to a particular job, it should be removed from the jobs table with the disown builtin (see Job Control Builtins) or marked to not receive SIGHUP using disown -h.

If the huponexit shell option has been set with shopt (see The Shopt Builtin), Bash sends a SIGHUP to all jobs when an interactive login shell exits.

If Bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes. When Bash is waiting for an asynchronous command via the wait builtin, the reception of a signal for which a trap has been set will cause the wait builtin to return immediately with an exit status greater than 128, immediately after which the trap is executed.

captura de tela demonstrativa

    
por 05.04.2013 / 23:40
0

Verifique o / etc / profile e o /etc/profile.d / *

Talvez haja algo que esteja com as configurações do histórico.

    
por 03.04.2013 / 13:46