Если у вас есть GNU sed
, это довольно просто:
sed -zi '/NoDisplay=true/!s/$/\nNoDisplay=true/' file
Опция -z
обрабатывает сразу всю строку в пространстве шаблонов (не рекомендуется для больших файлов ). Если параметр(!
)не найден, добавьте в конце встроенный символ новой строки. Примечание :-i
, -z
и \n
в замещающей строке не являются стандартными, поэтому они не переносимы.
Это не подтверждено другими источниками, а просто взгляд на дело.
Внимание! Это относится к кш -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
— это строка, которая записывает в файл истории.