Der BASH-Verlauf wurde bei jeder Anmeldung auf 500 Zeilen gekürzt

22

Aus irgendeinem Grund kann ich mein System nach einem Neustart nicht dazu bringen, meinen BASH-Verlauf zu speichern. Hier sind die relevanten Abschnitte meiner ~/.bashrc:

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

Soweit ich das beurteilen kann, gibt es alle erforderlichen Optionen (ich weiß, dass ich früher in der Lage war, den Verlauf über mehrere Neustarts hinweg zu verfolgen, ohne dass dies alles in der Vergangenheit passiert ist). Obwohl ich diese Optionen vor einigen Neustarts hinzugefügt habe, verliere ich nach einem Neustart immer noch den größten Teil meines Verlaufs. Es ist nicht leer, hat aber nicht die 9999 Leitungen, die ich vor dem Neustart hatte.

Bevor sich jemand beschwert, habe ich ja diese Fragen gelesen. Ich habe einige ihrer Vorschläge wie oben aufgeführt umgesetzt, der Rest war entweder nicht hilfreich oder nicht relevant:

Für den Fall, dass es möglicherweise andere relevante Befehle gibt, können Sie meinen gesamten Inhalt ~/.bashrc hier anzeigen .

Also, was fehle ich? Warum wird mein Verlauf nicht gespeichert? Wenn jemand der Meinung ist, dass eine andere Datei relevant sein könnte, lass es mich wissen und ich werde es veröffentlichen. Ich überprüfte, indem ich grep -i hist \.*mein $HOMEausführte, das zeigte, dass die einzige relevante .Akte, die die Zeichenkette enthielt histoder HISTwar .bashrc.

Ich verwende Linux Mint Debian Edition, GNU Bash, Version 4.2.36 (1) -Release (x86_64-pc-linux-gnu) und meinen bevorzugten Terminal-Emulator (falls relevant) terminator.


AKTUALISIEREN:

Dem Vorschlag von @ mpy in den Kommentaren folgend, habe ich meine ~/.bashrcEinstellung geändert und nicht HISTFILE=~/bash_historydie Standardeinstellung. Dies ~/.bash_historyscheint das Problem für interaktive Shells zu lösen . Anmelde-Shells zeigen immer noch dasselbe Verhalten, wobei der Verlauf in 500Zeilen abgeschnitten ist. In HISTden relevanten Dateien sind jedoch keine zugehörigen Variablen festgelegt:

$ 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

Also, warum setzt HISTSIZEund HISTFILESIZEin dem ~/.bashrcnicht genug , wenn ich explizit die $HISTFILEauf etwas anderes als der Standard ~/.bash_history?

terdon
quelle
Sind Sie der Eigentümer von .bash_history oder root? Do ls -l .bash_history
Adnan Bhatti
1
@MSStp ja, es gehört mir. Vielen Dank für den Vorschlag, aber ich sehe ohnehin kein Problem mit den Berechtigungen, entweder habe ich Lese- / Schreibzugriff darauf oder ich weiß nicht. Da einiges an Geschichte gerettet ist, mache ich das eindeutig. Wenn bash eine Einstellung hatte, die Probleme verursachte, wenn diese Datei nicht dem Benutzer gehört, würde sie sich entweder beschweren oder die gesamte Verlaufsfunktion würde nicht funktionieren.
Terdon
Wenn Sie den historyBefehl ausführen , ist die angezeigte Ausgabe identisch mit der angezeigten Ausgabe, abgesehen von cat .bash_historyden Zeilennummern. Ich meine, listet der historyBefehl Zeitstempel oder andere Informationen auf? Der Grund, den ich frage, ist, wenn Sie diese esoterischen Dinge sehen, bedeutet dies, dass es ein anderes Modul / eine andere Funktion / ein anderes Programm gibt, das mit der Shell-Historie in Konflikt gerät, und dass eine falsche oder fehlerhafte Version dessen, was auch immer es ist, Sie möglicherweise betrübt .
MelBurslan
@ Mel_Burslan ja es ist das gleiche, der einzige Unterschied ist die Zeilennummern.
Terdon
2
Ok, ein etwas seltsamer Vorschlag, aber es ist auch ein ungewöhnliches Problem ;): Probieren Sie eine andere Datei als HISTFILE aus, nicht die Standarddatei ~/.bash_history. Sehr konstruierte Erklärung: Ich gehe davon aus, dass bash Ihre Standard-Shell ist. Beim Systemstart ist also eine nicht interaktive Shell das übergeordnete Element Ihrer X-Sitzung (ich gehe auch davon aus, dass Sie X verwenden), die nichts über die Option histappend weiß (da .bashrc nur ist) gelesen von interaktiven Shells), so lange diese übergeordnete Shell ausgeführt wird, ist alles in Ordnung, aber beim Beenden (dh Systemstopp) wird es überschrieben ~/.bash_history(was Standard ist) und Ihre Geschichte
durcheinander gebracht

Antworten:

17

Das Problem ist auf das unterschiedliche Verhalten von Anmelde- und Nicht-Anmelde-Shells zurückzuführen. Ich hatte die Variablen, die den Verlauf steuern, in meinem festgelegt ~/.bahsrc. Diese Datei wird nicht gelesen, wenn eine Anmeldeshell gestartet wird. Sie wird nur von interaktiven Shells (von man bash) gelesen, die keine Anmeldeshells sind :

Wenn bash als interaktive Anmeldeshell oder als nicht interaktive Shell mit der --loginOption aufgerufen wird , werden zuerst die Befehle aus der Datei gelesen und ausgeführt /etc/profile, sofern diese Datei vorhanden ist. Nach dem Lesen dieser Datei wird nach ~ / .bash_profile ~/.bash_loginund ~/.profilein dieser Reihenfolge gesucht und es werden Befehle von der ersten Datei gelesen und ausgeführt, die vorhanden und lesbar ist. Die --noprofileOption kann verwendet werden, wenn die Shell gestartet wird, um dieses Verhalten zu unterbinden.

[. . . ]

Wenn eine interaktive Shell gestartet wird, die keine Anmeldeshell ist, liest bash Befehle von ~ / .bashrc und führt sie aus, sofern diese Datei vorhanden ist. Dies kann mit der Option --norc verhindert werden. Die Option --rcfile file erzwingt, dass Bash anstelle von ~ / .bashrc Befehle aus der Datei liest und ausführt.

Daher wurde die .historyDatei jedes Mal, wenn ich mich anmeldete, auf ein tty ablegte oder ssh verwendete, abgeschnitten, weil ich sie nicht auf die richtige Größe eingestellt hatte ~/.profile. Ich habe das endlich erkannt und stattdessen einfach die Variablen ~/.profile dort gesetzt, wo sie hingehören~/.bashrc

Der Grund, warum ich ~/.historyabgeschnitten wurde, war, dass ich nur die HISTORY-Variablen in einer Datei festgelegt hatte, die von interaktiven, nicht angemeldeten Shells gelesen wurde. Daher wurden die Variablen jedes Mal ignoriert, wenn ich einen anderen Shell-Typ ausführte, und die Datei wurde abgeschnitten entsprechend.

terdon
quelle
Sehr guter Punkt, danke fürs Teilen! Ich stimme jedoch nicht zu: Diese Datei wird beim Starten einer Login-Shell nicht gelesen, sondern nur von interaktiven Shells. Weil eine Login-Shell auch interaktiv sein kann. Andernfalls würde der gesamte Geschichtsmechanismus keinen Sinn ergeben. IMHO .bashrcwird nicht von (nicht interaktiven ODER Login-Shells) gelesen.
mpy
@mpy In der Tat, sorry, ich meinte interaktive Shells ohne Login. Antwort bearbeitet.
Terdon
1
@terdon, die gebräuchliche Redewendung ist, dass interaktive Shell-Optionen nicht in ~ / .profile oder ~ / .bash_profile passen. Interaktive Shell-Optionen werden in ~ / .bashrc abgelegt. Um zu vermeiden, dass die Einstellungen an zwei Stellen beibehalten werden müssen, können die folgenden Befehle am oberen Rand eines ~ / .bash_profile platziert export BASH_ENV=~/.bashrc ; if [ -f ~/.bashrc ]; then . ~/.bashrc; fiwerden: [ -z "$PS1" ] && return... Natürlich ist es nur eine Redewendung.
Noah Spurrier
1
@NoahSpurrier BASH_ENVist nicht relevant, es betrifft nur nicht interaktive Shells. Was die "Redewendung" betrifft, so hat Debian damit begonnen und ich persönlich bin damit nicht einverstanden. Ich habe häufig grafische Optionen ( xsetund ähnliches) in meinem .bashrc und ich möchte nicht, dass diese aktiv sind, wenn ich Login-Shells von einem tty oder durchlaufe ssh. Ich möchte mein .profile und .bashrc getrennt haben. Viele (wenn auch nicht alle) Anmeldemanager geben beim Anmelden .profile ein, sodass globale Variablen am besten dort festgelegt werden, wo sie nur einmal und nicht bei jedem Öffnen eines Terminals gelesen werden.
Terdon
1
@ WilsonF ja. Die Dateien werden nacheinander gelesen und die persönlichen Dateien ( ~/.profileoder ~/.bashrc) werden zuletzt gelesen. Alles, was in diesen Einstellungen festgelegt ist, hat Vorrang vor den globalen Einstellungen. Sie haben vollkommen recht, Sie sollten diese Variablen nicht eingeben /etc/bash.bashrc. Verwenden Sie stattdessen ~/.profile(oder ~/.bash_profile).
Terdon
11

Mein Vorschlag ist, eine andere Datei als zu verwenden HISTFILE, nicht die Standardeinstellung ~/.bash_history.

Obwohl ich keine analytische Erklärung habe, werde ich versuchen zu skizzieren, was mich zu diesem Vorschlag geführt hat: Wenn Sie bashals Standard-Shell (Login-Shell) verwenden und X(was beide sehr wahrscheinlich sind), haben Sie bashdirekt nach der (grafischen ) eine laufende Instanz ) Anmeldung:

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

Ich denke, diese Instanz ist eine Login-Shell, daher liest sie Ihre ~/.bashrcnicht und weiß daher nichts über die histappendOption:

man bash (1) : Wenn eine interaktive Shell gestartet wird, die keine Anmeldeshell ist, liest bash Befehle aus /etc/bash.bashrc und ~ / .bashrc und führt sie aus, sofern diese Dateien vorhanden sind. (...)

Solange diese "übergeordnete Shell" ausgeführt wird, ist alles in Ordnung, aber bei Beendigung (dh Systemstopp) wird sie überschrieben ~/.bash_history(da dies der Standardwert ist) und Ihren Verlauf durcheinander bringen oder ihn beim Systemstart auf (wieder Standard) 500 beschneiden Linien. (Oder vielleicht beides ...)

Mir fällt auch auf, dass es nicht ausreicht, die Verlaufskonfiguration mit einzubeziehen ~/.bashrc, da dies kein so ungewöhnliches Setup sein sollte. Ich habe keine Erklärung dafür.


In Bezug auf Ihr Problem, dass "Login-Shells immer noch dasselbe Verhalten zeigen", können Sie versuchen, die Verlaufskonfiguration auch in Folgendes aufzunehmen ~/.bash_profile:

man bash (1) : Wenn bash als interaktive Anmeldeshell oder als nicht interaktive Shell mit der Option --login aufgerufen wird, werden zuerst Befehle aus der Datei / etc / profile gelesen und ausgeführt, sofern diese Datei vorhanden ist. Nach dem Lesen dieser Datei sucht sie nach ~ / .bash_profile, (...)

Leider kann ich keine gerechtfertigtere Erklärung mit Details aus meiner eigenen bashKonfiguration posten , da ich ein zshTyp bin ...

mpy
quelle
2
Das explizite Festlegen der Verlaufsoptionen in meinem ~/.bash_profilelöste das Problem. Ich verwende jetzt ~/.bash_historyals Verlaufsdatei, habe aber einfach alle ~/.bashrcin meiner Frage gezeigten Zeilen hinzugefügt ~/.bash_profile. Ich bin mir immer noch nicht sicher, wer die interaktiven Shells vermasselt hat, aber es scheint jetzt zu funktionieren, danke!
Terdon
1
Tut mir leid, dass ich das nicht akzeptiert habe, aber ich hatte vergessen, eine Antwort zu schreiben, in der erklärt wurde, was los war. Ich habe es vor einiger Zeit mit Hilfe von @Gilles herausgefunden und bin endlich dazu gekommen, eine Antwort zu schreiben. Ich wollte meine akzeptieren, weil sie das Problem tatsächlich erklärt, anstatt eine (sehr gute) Problemumgehung anzubieten, und zukünftigen Besuchern helfen könnte.
Terdon
2

Da alle Ihre Einstellungen gemäß der Manpage in der richtigen Reihenfolge sind und die Verlaufsdatei nicht durch die Größe (Bytes) beschränkt ist, ist die einzig mögliche Erklärung, die ich mir vorstellen kann. Es hat damit zu tun, wie die Schale stirbt.

Gemäß der Online-Referenz erfolgt das ordnungsgemäße Verlassen (Speichern des Verlaufs) nur, wenn die Shell SIGHUP empfängt. Ich kann nicht wirklich erklären, wie Ihr System beim Neustart Signale weitergibt, aber ich vermute, dass Ihre Shell mit SIGKILL oder SIGPWR beendet wird.

Dies kann daran liegen, dass Ihr WM asynchron ausgeführt wird (warten) und der Terminalemulator aus dem WM stammt, in dem die Bash ein anderes Ausgangssignal als SIGHUP erhält. Es kann auch sein, dass das Betriebssystem zu schnell den "final kill" an alle Prozesse sendet, bevor das ursprüngliche SIGHUP es schafft, über X -> WM -> xterm zur Shell zu gelangen, möglicherweise weil das Beenden von X oder WM länger dauert als Es dauert, bis das Betriebssystem betriebsbereit ist.

Ich bin auf tiefen Gewässern mit diesem Zeug, aber ich denke, dass etwas in dieser Richtung das unberechenbare Verhalten verursacht. Ich hatte dieses Problem schon einmal und das beste Mittel ist die exitBash, bei der Sie die Geschichte aufzeichnen möchten.

Mir ist history -ain Ihrer Frage aufgefallen , und ich kann mir nicht vorstellen, warum das nicht ausreichen würde, um die Geschichte zu bewahren.

Sie können das Problem beheben, indem Sie herausfinden, was Ihre Bash wirklich tötet, und dann herausfinden, wo das Signal herkommt, und das Problem dort beheben ):

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...

Der beigefügte Screenshot zeigt, worüber ich im zweiten und dritten Absatz spreche. Die Sequenz dort ist, in der ich von links schale , die linke von rechts schale töte und die Geschichte katze.

Mann Bash

Beim Start wird (...) die durch den Wert von HISTFILE angegebene Datei gekürzt, um nicht mehr als die durch den Wert von HISTFILESIZE angegebene Anzahl von Zeilen zu enthalten (+ Standard 500).

Wenn die Shell-Option histappend aktiviert ist (+ hier standardmäßig), werden die Zeilen an die Verlaufsdatei angehängt, andernfalls wird die Verlaufsdatei überschrieben.

Online-Referenz

3.7.6 Signale

Wenn Bash interaktiv ist und keine Fallen vorhanden sind, ignoriert es SIGTERM (damit 'kill 0' keine interaktive Shell beendet) und SIGINT wird abgefangen und behandelt (damit das eingebaute Warten unterbrochen werden kann). Wenn Bash ein SIGINT empfängt, bricht es alle ausgeführten Schleifen ab. In allen Fällen ignoriert Bash SIGQUIT. Wenn die Auftragssteuerung aktiviert ist (siehe Auftragssteuerung), ignoriert Bash SIGTTIN, SIGTTOU und SIGTSTP.

Bei nicht integrierten Befehlen, die von Bash gestartet werden, werden die Signalhandler auf die Werte gesetzt, die die Shell von ihrem übergeordneten Element übernommen hat. Wenn die Jobsteuerung nicht aktiviert ist, ignorieren asynchrone Befehle zusätzlich zu diesen geerbten Handlern SIGINT und SIGQUIT. Befehle, die als Ergebnis der Befehlsersetzung ausgeführt werden, ignorieren die von der Tastatur generierten Auftragssteuersignale SIGTTIN, SIGTTOU und SIGTSTP.

Die Shell wird standardmäßig nach Erhalt eines SIGHUP beendet. Vor dem Beenden sendet eine interaktive Shell das SIGHUP erneut an alle laufenden oder gestoppten Jobs. Angehaltene Jobs werden an SIGCONT gesendet, um sicherzustellen, dass sie den SIGHUP erhalten. Um zu verhindern, dass die Shell das SIGHUP-Signal an einen bestimmten Job sendet, sollte dieser mit dem nicht vorhandenen Build (siehe Job Control Builtins) aus der Job-Tabelle entfernt oder mit disown -h markiert werden, um SIGHUP nicht zu empfangen.

Wenn die Shell-Option huponexit mit shopt festgelegt wurde (siehe The Shopt Builtin), sendet Bash beim Beenden einer interaktiven Login-Shell einen SIGHUP an alle Jobs.

Wenn Bash auf den Abschluss eines Befehls wartet und ein Signal empfängt, für das ein Trap festgelegt wurde, wird der Trap erst ausgeführt, wenn der Befehl abgeschlossen ist. Wenn Bash auf einen asynchronen Befehl über die eingebaute Warteschleife wartet, kehrt die eingebaute Warteschleife beim Empfang eines Signals, für das eine Trap gesetzt wurde, sofort mit einem Ausgangsstatus von mehr als 128 zurück, unmittelbar nachdem die Trap ausgeführt wurde.

Demonstrativer Screenshot

Signale

Ярослав Рахматуллин
quelle
Ich verstehe nicht wirklich, was Sie in diesem Screenshot tun. Was ist das /tmp/pso, was du tötest? Ich verstehe Ihren Standpunkt zu den verschiedenen Kill-Signalen (obwohl ich, wie Sie sagen, dachte, dass es das history -aist, womit man sich befassen muss). Ich werde das eine Weile testen und berichten.
Terdon
$ cat tmp / ps * \ n ps -o pid = | head -n1> ~ / tmp / pso \ n 17201 \ n
Ярослав Рахматуллин
0

Überprüfen Sie / etc / profile und /etc/profile.d/*

Vielleicht gibt es da etwas, das mit den Verlaufseinstellungen zu tun hat.

Mabagu
quelle
Danke, aber grep -r HIST /etc/profile.d/nichts zurück, und ich habe bereits geprüft /etc/profile.
Terdon