Почему я внезапно не могу получить доступ к своей истории командной строки?

Если у вас есть GNU sed, это довольно просто:

sed -zi '/NoDisplay=true/!s/$/\nNoDisplay=true/' file

Опция -zобрабатывает сразу всю строку в пространстве шаблонов (не рекомендуется для больших файлов ). Если параметр(!)не найден, добавьте в конце встроенный символ новой строки. Примечание :-i, -zи \nв замещающей строке не являются стандартными, поэтому они не переносимы.

3
26.05.2021, 17:00
1 ответ

Это не подтверждено другими источниками, а просто взгляд на дело.

Внимание! Это относится к кш -2020.

Существует ошибка в обработке истории, когда история превышает определенный размер (байт ). Это проявляется в том, что длина истории равна 1 (или нулю )и остается на этом уровне. Если вы достигаете предела, который вызывает ошибку в ksh, она проявляется при следующем запуске.

Использование чего-то вроде:

PS1='$_pwd [!]\$ '

показывает путь + количество записей истории.

При нормальном запускеsh_histinitвызывается при запуске. По какой-то неизвестной причине эта функция вызывается для каждой команды , когда эта ошибка активна. Далее обычно вызываетсяhist_writeдля записи записи, но это не вызывается, когда ошибка активна.

В результате получаетсяновый файловый дескриптор спо .sh_hisoryдлякаждой команды. Это, вероятно, то, что вы также видели в /proc/PID/fd, как указано в комментариях. Дальнейшие команды в файл не записываются.

Решение, по крайней мере здесь, состоит в том, чтобы заархивировать старую историю и начать новую. Вероятно, рекомендуется перезапустить оболочку.

Если HISTSIZEне определено, предел для срабатывания ошибки невелик. Несколько сотен записей. Вы можете установить большое число, например 50000, чтобы «задержать» его. В моих тестах он запускался примерно на 32 тыс. строк с размером 50000. Увеличил размер до 500000, а затем снова заработал, как и ожидалось.

Как уже отмечалось, также рекомендуется установить ksh93вместо версии 2020. Судя по всему, 2020 год застопорился.(93не означает, что он из 1993 года -, но основан на этой версии. Вероятно93u)

В версии 93uэтой ошибки нет.

Если /etc/skel/.kshrcне является источником, вы, вероятно, также захотите скопировать этот файл в свой домашний каталог. У , вероятно, уже есть набор HISTSIZE, измените его на большое значение, если вы продолжите работу с выпуском 2020.



Оригинальный "комментарий"

Это слишком длинно для комментария, поэтому я пишу это как «ответ». (Предполагается Linux)

Вы могли бы найти ключ к разгадке происходящего,:


В одном терминале запустите 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[...прочитать 65536 байт из fd 3 , прочитать файл истории.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

— это строка, которая записывает в файл истории.

1
28.07.2021, 11:29

Теги

Похожие вопросы