Utilizo ksh
(versión: sh (AT&T Research) 2020.0.0) en Ubuntu 20.04 y uso el modo de edición de línea de comandos vi ( set -o vi
). Esto ha funcionado bien durante años, pero recientemente he notado algunas rarezas y finalmente esta mañana dejó de funcionar por completo.
- Veo que los comandos ya no se guardan
~/.sh_histfile
a partir de esta mañana. - En el pasado, todos los comandos que ingresaba se podían encontrar desplazándose hacia arriba con Escko, por ejemplo. buscando con Esc/.
- Hace un tiempo, esto pareció cambiar y solo recordar comandos exitosos (lo cual es una molestia).
Ayer no hice ningún cambio en mi configuración (creo), pero el historial de la línea de comandos funciona para el usuario root.
Los permisos ~/.sh_histfile
son 600 y HISTFILE
no están configurados, ni para mi usuario normal ni para mi root.
¿Alguna idea de qué salió mal y, por supuesto, cómo solucionarlo? Lo ideal sería volver a la situación en la que todo lo que escribí en la línea de comando y terminé Enterse guardaría en ~/.sh_histfile
.
Editar
Se establecen las siguientes variables:
$ 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
El perfil local contiene solo elementos predeterminados y un par de líneas al final que agregué:
$ 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
Respuesta1
Esto esNo verificadopor otras fuentes, sino simplemente una mirada al caso.
¡NÓTESE BIEN! Esto se relaciona con ksh-2020.
Hay un error en el manejo del historial cuando el historial supera un cierto tamaño (bytes). Se manifiesta en que la longitud del historial es 1 (también conocido como cero) y permanece ahí. Si uno alcanza el límite que desencadena el error mientras está en ksh
él, se manifestará en la próxima ejecución.
Usando algo como:
PS1='$_pwd [!]\$ '
muestra la ruta + número de entradas del historial.
En una carrera normalsh_histinit
se llama al inicio. Por alguna razón, no rastreada, esta función se llamapara cada comandocuando este error está activo. Máshist_write
Normalmente se llama para escribir el registro, pero no se llama cuando el error está activo.
Como resultado uno termina conun nuevo descriptor de archivoa .sh_hisory
paracada comando. Es probable que esto sea lo que también vio /proc/PID/fd
en los comentarios. Otros comandos no se escriben en el archivo.
La solución, al menos aquí, es archivar la historia antigua y comenzar una nueva. Probablemente sea aconsejable reiniciar Shell.
Sin HISTSIZE
definirlo, el límite para activar el error es pequeño. Unos cientos de registros. Puedes configurarlo en un número grande, como 50000, para "retrasarlo". En mis pruebas, se activaron alrededor de 32k líneas con un tamaño de 50000. Aumenté el tamaño a 500000 y luego funcionó como se esperaba nuevamente.
Como se señaló, también es probable que sea recomendable instalarla ksh93
en lugar de la versión 2020. Por lo que parece, el 2020 se ha estancado. ( 93
No significa que sea de 1993, sino que se basa en esa versión. Probablemente 93u
)
La 93u
versión no tiene este error.
Si /etc/skel/.kshrc
no se obtiene, es probable que también desee copiar ese archivo a su directorio de inicio. ÉlprobableYa tienes un HISTSIZE
conjunto, cámbialo a un valor grande si continúas con la versión 2020.
"Comentario" original
Esto es demasiado largo para un comentario, así que lo escribo como una "respuesta". (Asumiendo Linux)
Posiblemente puedas encontrar una pista de lo que está pasando:
En una terminal funciona ksh
normalmente. Obtén el pid de ese caparazón.
Controlar /proc/PID/fd/
. Normalmente debería tener abierto fd 3 a/home/username/.sh_history
En el segundo caparazón hazlo strace -p PID
. En el primer shell, cuando ingresa, k
normalmente debería ver algo como esto en el shell ejecutándose strace
.
Leer la historia por 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
Aquí:
read(0, "k", 80) = 1
leer desde STDIN, lee 1 byte, "k" (La clave ingresada)
read(3, "\201\1[ ...
leer 65536 bytes de fd 3, lea el archivo de historial.
write(2, "man foo...
escribirman foo
, se muestra el comando anterior.
Escribir historia:
En el primer shell ingrese un comando. En el registro a continuación entré cd irc
desde~/tmp
Extracto deentrandoc<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
Aquí el:
write(3, "cd irc\n\0", 8) = 8
es la línea que escribe en el archivo histórico.