Ich verwende ksh
(Version: sh (AT&T Research) 2020.0.0) unter Ubuntu 20.04 und verwende den vi-Befehlszeilenbearbeitungsmodus ( set -o vi
). Das hat jahrelang gut funktioniert, aber in letzter Zeit sind mir einige Merkwürdigkeiten aufgefallen, und heute Morgen hat es schließlich ganz aufgehört zu funktionieren.
~/.sh_histfile
Ich sehe, dass seit heute Morgen keine Befehle mehr gespeichert werden- Alle von mir eingegebenen Befehle konnte ich bisher durch ein Hochscrollen mit Esckoder zB. eine Suche mit finden Esc/.
- Vor einiger Zeit schien sich dies dahingehend geändert zu haben, dass nur noch erfolgreiche Befehle gespeichert werden (was lästig ist).
Ich habe gestern keine Änderungen an meiner Konfiguration vorgenommen (glaube ich), aber der Befehlszeilenverlauf funktioniert für den Root-Benutzer.
Die Berechtigungen ~/.sh_histfile
liegen bei 600 und HISTFILE
sind weder für meinen normalen Benutzer noch für Root festgelegt.
Irgendeine Idee, was schiefgelaufen ist – und natürlich, wie man es behebt? Idealerweise möchte ich zu der Situation zurückkehren, in der alles, was ich in der Befehlszeile geschrieben und fertiggestellt habe, Enterin gespeichert wird ~/.sh_histfile
.
Bearbeiten
Die folgenden Variablen werden gesetzt:
$ set
_=export
COMP_CWORD=0
COMP_KEY=0
COMP_POINT=0
COMP_TYPE=0
COMP_WORDBREAKS=$'"\'@><=;|&(:'
DBUS_SESSION_BUS_ADDRESS='unix:path=/run/user/1000/bus'
DISPLAY=localhost:11.0
ENV=/home/jan.andersen/.kshrc
FCEDIT=/usr/bin/ex
HISTCMD=1
HOME=/home/jan.andersen
IFS=$' \t\n'
JOBMAX=0
KSH_VERSION=.sh.version
LANG=en_US.UTF-8
LESS=X
LINENO=1
LOGNAME=jan.andersen
MAILCHECK=600
MOTD_SHOWN=pam
OLDPWD=/home/jan.andersen
OPTIND=1
PATH=/home/jan.andersen/.local/bin:/usr/local/glassfish5/bin:/usr/local/glassfish5/glassfish/bin:/usr/local/texlive/2019/bin/x86_64-linux:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
PPID=3887
PS1=$'\'$ \''
PS2='> '
PS3='#? '
PS4='+ '
PWD=/home/jan.andersen
RANDOM=18082
SECONDS=17131.589
SHELL=/usr/bin/ksh
SHLVL=1
SH_OPTIONS=astbin=/opt/ast/bin
SSH_TTY=/dev/pts/1
TERM=xterm-256color
TMOUT=0
USER=jan.andersen
XDG_RUNTIME_DIR=/run/user/1000
XDG_SESSION_CLASS=user
XDG_SESSION_ID=10
XDG_SESSION_TYPE=tty
Das lokale Profil enthält nur Standardinhalte und am Ende ein paar Zeilen, die ich hinzugefügt habe:
$ cat .profile
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.
# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH"
fi
#eval $(ssh-agent -s)
#ssh-add ~/.ssh/id_rsa
export SSH_AUTH_SOCK=${XDG_RUNTIME_DIR}/ssh-agent.socket
Antwort1
Das istnicht verifiziertdurch andere Quellen, sondern lediglich ein Blick auf den Fall.
NB! Dies bezieht sich auf ksh-2020.
Es gibt einen Fehler bei der Handhabung des Verlaufs, wenn der Verlauf eine bestimmte Größe (Bytes) überschreitet. Dies äußert sich darin, dass die Verlaufslänge 1 (also null) beträgt und dort bleibt. Wenn das Limit erreicht wird, wird der Fehler beim ksh
nächsten Durchlauf ausgelöst.
Verwenden Sie etwas wie:
PS1='$_pwd [!]\$ '
zeigt Pfad + Anzahl der Verlaufseinträge.
Bei einem normalen Laufsh_histinit
wird beim Start aufgerufen. Aus einem Grund, der nicht ermittelt werden kann, wird diese Funktion aufgerufenfür jeden Befehlwenn dieser Fehler aktiv ist. Weiterehist_write
wird normalerweise aufgerufen, um den Datensatz zu schreiben, wird aber nicht aufgerufen, wenn der Fehler aktiv ist.
Als Ergebnis erhält manein neuer Dateideskriptorzu .sh_hisory
fürjeder Befehl. Dies ist wahrscheinlich das, was Sie auch /proc/PID/fd
in den Kommentaren gesehen haben. Weitere Befehle werden nicht in die Datei geschrieben.
Die Lösung besteht zumindest hier darin, den alten Verlauf zu archivieren und einen neuen zu beginnen. Wahrscheinlich ist es ratsam, die Shell neu zu starten.
Ohne HISTSIZE
Definition ist die Grenze, ab der der Fehler ausgelöst wird, gering. Ein paar hundert Datensätze. Sie können eine große Zahl wie 50000 festlegen, um ihn zu „verzögern“. In meinen Tests wurde er dann bei etwa 32.000 Zeilen mit einer Größe von 50000 ausgelöst. Ich habe die Größe auf 500000 erhöht und dann funktionierte es wieder wie erwartet.
ksh93
Wie erwähnt ist es wahrscheinlich auch ratsam , anstelle der Version 2020 zu installieren . So wie es aussieht, ist die Version 2020 ins Stocken geraten. ( 93
bedeutet nicht, dass sie aus dem Jahr 1993 ist – basiert aber auf dieser Version. Wahrscheinlich 93u
)
Die 93u
Version hat diesen Fehler nicht.
Wenn /etc/skel/.kshrc
keine Quelle vorhanden ist, möchten Sie diese Datei wahrscheinlich auch in Ihr Home-Verzeichnis kopieren. EswahrscheinlichSie haben bereits einen HISTSIZE
Satz, ändern Sie diesen in einen großen Wert, wenn Sie mit der Version 2020 fortfahren.
Ursprünglicher „Kommentar“
Das ist zu lang für einen Kommentar, deshalb schreibe ich es als „Antwort“. (Unter der Annahme von Linux)
Einen Hinweis darauf, was los ist, finden Sie möglicherweise durch:
Führen Sie es normal in einem Terminal aus ksh
. Holen Sie sich die PID dieser Shell.
Überprüfen Sie /proc/PID/fd/
. Es sollte in der Regel offene fd 3 haben, um/home/username/.sh_history
Geben Sie in der zweiten Shell ein strace -p PID
. Wenn Sie in der ersten Shell eingeben, k
sollten Sie in der ausgeführten Shell normalerweise so etwas sehen strace
.
Lesen Sie die Geschichte von k
:
select(1, [0], NULL, NULL, NULL) = 1 (in [0])
recvfrom(0, 0x7ffdcff6c0d0, 80, MSG_PEEK, NULL, NULL) = -1 ENOTSOCK (Socket operation on non-socket)
read(0, "k", 80) = 1
lseek(3, 0, SEEK_SET) = 0
lseek(3, 0, SEEK_SET) = 0
read(3, "\201\1[ --help\n\0exit\n\0env\n\0\0ls\n\0q\n\0\0"..., 65536) = 258
lseek(3, 0, SEEK_END) = 258
write(2, "man foo\10\10\10\10\10\10\10", 14) = 14
Hier:
read(0, "k", 80) = 1
von STDIN lesen, 1 Byte lesen, „k“ (Der eingegebene Schlüssel)
read(3, "\201\1[ ...
65536 Bytes von fd 3 gelesen, Verlaufsdatei lesen.
write(2, "man foo...
schreibenman foo
, der vorherige Befehl wird angezeigt.
Geschichte schreiben:
Geben Sie in der ersten Shell einen Befehl ein. Im folgenden Protokoll habe ich cd irc
Folgendes eingegeben:~/tmp
Ausschnitt ausEingabec<Enter>
write(2, "c", 1) = 1
select(1, [0], NULL, NULL, NULL) = 1 (in [0])
recvfrom(0, 0x7ffdcff6c0d0, 80, MSG_PEEK, NULL, NULL) = -1 ENOTSOCK (Socket operation on non-socket)
read(0, "\r", 80) = 1
ioctl(2, TCGETS, {B38400 opost -isig -icanon -echo ...}) = 0
ioctl(2, SNDCTL_TMR_START or TCSETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
write(2, "\n", 1) = 1
lseek(3, 0, SEEK_END) = 270
lseek(3, 0, SEEK_CUR) = 270
lseek(3, 270, SEEK_SET) = 270
read(3, "", 65536) = 0
lseek(3, 0, SEEK_END) = 270
lseek(3, 0, SEEK_END) = 270
write(3, "cd irc\n\0", 8) = 8
lseek(3, 0, SEEK_CUR) = 278
chdir("irc") = 0
lseek(3, 0, SEEK_END) = 278
lseek(3, 278, SEEK_SET) = 278
lseek(3, 278, SEEK_SET) = 278
read(3, "", 65536) = 0
write(2, "~/tmp/irc [36]$ ", 16) = 16
Hier das:
write(3, "cd irc\n\0", 8) = 8
ist die Zeile, die in die Verlaufsdatei schreibt.