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

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

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

  • ~/.sh_histfile오늘 아침부터 명령이 더 이상 저장되지 않은 것을 알 수 있습니다.
  • 과거에는 내가 입력한 모든 명령을 를 Esck사용하거나 위로 스크롤하여 찾을 수 있었습니다. 로 검색하세요 Esc/.
  • 얼마 전까지만 해도 이것이 성공한 명령을 기억하는 것뿐인 것 같았습니다(고통스럽습니다).

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

권한 ~/.sh_histfile은 600이며 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으로 늘리면 예상대로 다시 작동합니다.

언급한 대로 ksh932020 버전 대신 설치하는 것이 권장될 수도 있습니다. 표면적으로 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

히스토리 파일에 기록된 행입니다.

관련 정보