갑자기 명령줄 기록에 액세스할 수 없는 이유는 무엇입니까?

갑자기 명령줄 기록에 액세스할 수 없는 이유는 무엇입니까?

저는 kshUbuntu 20.04에서 (버전: sh (AT&T Research) 2020.0.0)을 사용하고 있으며, vi 명령줄 편집 모드( set -o vi)를 사용하고 있습니다. 이것은 몇 년 동안 잘 작동했지만 최근에 몇 가지 이상한 점을 발견했고 마침내 오늘 아침에 완전히 작동이 멈췄습니다.

  • ~/.sh_histfile오늘 아침부터 명령이 더 이상 저장되지 않는 것을 볼 수 있습니다.
  • 과거에는 내가 입력한 모든 명령을 Esck또는 예를 들어 위로 스크롤하여 찾을 수 있었습니다. 로 검색 중입니다 Esc/.
  • 얼마 전에는 성공한 명령만 기억하는 것으로 바뀌는 것 같았습니다(이건 귀찮습니다).

어제 구성을 변경하지 않았지만(내 생각에는) 명령줄 기록이 루트 사용자에 대해 작동합니다.

권한은 ~/.sh_histfile600이며 HISTFILE일반 사용자나 루트에 대해 설정되지 않았습니다.

무엇이 잘못되었는지, 그리고 어떻게 고치는지 아시나요? 이상적으로는 명령줄에 쓰고 끝낸 모든 내용 Enter~/.sh_histfile.

편집하다

다음 변수가 설정됩니다.

$ 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

로컬 프로필에는 기본 항목과 내가 추가한 몇 줄의 줄만 포함되어 있습니다.

$ 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

답변1

이것은확인되지 않음다른 출처에 따르면, 단지 사례를 살펴보겠습니다.

주의! 이는 ksh-2020과 관련이 있습니다.

히스토리가 특정 크기(바이트)를 초과하면 히스토리 처리에 버그가 있습니다. 이는 히스토리 길이가 1(일명 0)이고 그 상태를 유지한다는 점에서 나타납니다. 버그가 발생하는 한계에 도달하면 ksh다음 실행 시 버그가 나타납니다.

다음과 같은 것을 사용합니다:

PS1='$_pwd [!]\$ '

경로 + 기록 항목 수를 표시합니다.

정상적인 실행에서는sh_histinit시작 시 호출됩니다. 어떤 이유로 추적되지 않고 이 함수가 호출됩니다.모든 명령에 대해이 버그가 활성화되면. 더 나아가hist_write일반적으로 레코드를 작성하기 위해 호출되지만 버그가 활성화되면 호출되지 않습니다.

결과적으로 하나는새로운 파일 설명자.sh_hisory~ 을 위해모든 명령. 이는 /proc/PID/fd댓글에서 언급한 바와 같이 귀하도 본 내용일 가능성이 높습니다 . 추가 명령은 파일에 기록되지 않습니다.

적어도 여기서 해결책은 오래된 역사를 보관하고 새로운 역사를 시작하는 것입니다. 쉘을 다시 시작하는 것이 좋습니다.

정의 하지 않으면 HISTSIZE버그를 유발하는 한계가 작습니다. 수백 개의 기록. 50000과 같은 큰 숫자로 설정하여 "지연"할 수 있습니다. 내 테스트에서는 크기가 50000인 약 32,000개의 라인이 트리거되었습니다. 크기를 500000으로 늘린 다음 다시 예상대로 작동했습니다.

ksh93언급한 대로 2020 버전 대신 설치하는 것이 좋습니다 . 사물의 모습으로 볼 때 2020년은 정체되었습니다. ( 931993년의 것이라는 의미는 아니지만 해당 버전을 기반으로 합니다. 아마도 93u)

해당 93u버전에는 이 버그가 없습니다.

소스가 아닌 경우 /etc/skel/.kshrc해당 파일을 홈 디렉터리에 복사할 수도 있습니다. 그것~할 것 같은이미 HISTSIZE세트가 있는 경우 2020 릴리스를 계속 진행하려면 해당 세트를 큰 값으로 변경하세요.



원래 "댓글"

댓글로 달기엔 너무 길어서 "답변"으로 씁니다. (리눅스 가정)

다음을 통해 무슨 일이 일어나고 있는지에 대한 단서를 찾을 수 있습니다.


한 터미널에서는 ksh정상적으로 실행됩니다. 해당 쉘의 pid를 얻으십시오.

확인하다 /proc/PID/fd/. 일반적으로 fd 3을 열어야 합니다./home/username/.sh_history

두 번째 쉘에서는 strace -p PID. 첫 번째 셸에 들어가면 k일반적으로 실행 중인 셸에서 다음과 같은 내용을 볼 수 있습니다 strace.

기록 읽기 기준 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

여기:

read(0, "k", 80) = 1 STDIN에서 읽기, 1바이트 읽기, "k"(입력된 키)
read(3, "\201\1[ ... fd 3에서 65536바이트를 읽습니다., 기록 파일을 읽습니다. write(2, "man foo... 쓰다man foo, 이전 명령이 표시됩니다.

기록 쓰기:

첫 번째 셸에서 명령을 입력합니다. 아래 로그에서 나는 cd irc다음에서 입력했습니다.~/tmp

에서 발췌입력c<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

여기에는:
write(3, "cd irc\n\0", 8) = 8

히스토리 파일에 쓰는 라인입니다.

관련 정보