저는 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으로 늘리면 예상대로 다시 작동합니다.
언급한 대로 ksh93
2020 버전 대신 설치하는 것이 권장될 수도 있습니다. 표면적으로 2020년은 정체되었습니다. ( 93
1993년의 것이라는 의미는 아니지만 해당 버전을 기반으로 한 것입니다. 아마도 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
히스토리 파일에 기록된 행입니다.