Почему я теряю историю ZSH?

Вawk:

                 { isblank = 0 }
/^[[:blank:]]*$/ { isblank = 1 }

state == 0 &&  isblank { next }
state == 0 && !isblank { state = 1 }

state == 1 &&  isblank { buffer[++n] = $0 }
state == 1 && !isblank { for (i = 1; i <= n; ++i) print buffer[i]; n = 0; print }

stateобозначает, в каком состоянии находится программа. Когда state == 0, программа удалит все пустые строки. Пустая строка — это строка, которая пуста или содержит только пробелы или символы табуляции (, что соответствует [[:blank:]]). Программа остается в state == 0до тех пор, пока не будет найдена не-пустая строка. Это обрезает начало файла.

При state == 1программа будет сохранять пустые строки в массив buffer. Эти пустые строки необходимо вывести, как только будет найдена пустая строка, отличная от -. Если не найдено не -пустых строк, они будут отброшены (, это обрезает конец файла ).

Общий эффект заключается в том, что пустые строки в начале и конце файла удаляются, в то время как пустые строки в других местах сохраняются (, включая их пробелы или табуляции, если они содержались в исходном файле ).

Тестирование:

$ cat file



Three blank lines above


Two blank lines in the middle
Three blank lines below



$ awk -f trim.awk file
Three blank lines above


Two blank lines in the middle
Three blank lines below

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

$ awk -f trim.awk file | sed -e '1s/^[[:blank:]]*//' -e '$s/[[:blank:]]*$/'
8
21.02.2020, 12:40
5 ответов

У меня была аналогичная проблема, и я только сегодня понял ее.

Я использую о -мой -zsh, который устанавливает SAVEHIST=10000. В моей истории было более 10 000 строк, но я думаю, что самые старые команды удалены, чтобы освободить место для новых, и 10 000 работали нормально. Однако у меня была другая проблема с -моим -zsh, которую я отлаживал, и в какой-то момент полностью удалил . $ZSH/oh-my-zsh.shиз моего zshrc, это привело к сбросу SAVEHISTдо значения по умолчанию 1000. ], а zsh быстро удалил остальные 9000строк из моего файла истории. Если у вас открыто другое окно терминала, когда это происходит, вы все равно можете запустить historyиз этого окна, чтобы увидеть свою полную историю, но как только вы закроете этот сеанс, он исчезнет навсегда (, если, конечно, у вас нет резервных копий ).

2
28.04.2021, 23:22

ЗШ

Файл истории может быть усечен/утерян/очищен по нескольким причинам,:

  • Повреждение файла истории zsh (из-за отключения питания -/сбоя системы -при открытии оболочки, в этом случае необходимо настроить fsck для запуска при сбое системы)
  • Файл конфигурации Zsh не загружен (, например, если $HOMEпеременная env не определена)
  • Неподдерживаемый символ в файле истории может заставить zsh сбросить историю
  • Чистящие средства, такие как отбеливатель
  • Неправильная конфигурация Zsh
  • и др.

Примечания

История доступных параметров настройки

HISTFILE="$HOME/.zsh_history"
HISTSIZE=500000
SAVEHIST=500000
setopt BANG_HIST                 # Treat the '!' character specially during expansion.
setopt EXTENDED_HISTORY          # Write the history file in the ":start:elapsed;command" format.
setopt INC_APPEND_HISTORY        # Write to the history file immediately, not when the shell exits.
setopt SHARE_HISTORY             # Share history between all sessions.
setopt HIST_EXPIRE_DUPS_FIRST    # Expire duplicate entries first when trimming history.
setopt HIST_IGNORE_DUPS          # Don't record an entry that was just recorded again.
setopt HIST_IGNORE_ALL_DUPS      # Delete old recorded entry if new entry is a duplicate.
setopt HIST_FIND_NO_DUPS         # Do not display a line previously found.
setopt HIST_IGNORE_SPACE         # Don't record an entry starting with a space.
setopt HIST_SAVE_NO_DUPS         # Don't write duplicate entries in the history file.
setopt HIST_REDUCE_BLANKS        # Remove superfluous blanks before recording entry.
setopt HIST_VERIFY               # Don't execute immediately upon history expansion.
setopt HIST_BEEP                 # Beep when accessing nonexistent history.

Ответ

В этой ситуации рекомендуется следующая конфигурация (для настройки в файле ~/.zshrc)

HISTFILE=/specify/a/fixed/and/different/location/.history
HISTSIZE=500000
SAVEHIST=500000
setopt appendhistory
setopt INC_APPEND_HISTORY  
setopt SHARE_HISTORY

Альтернатива

Вы можете использовать небольшой скрипт, который проверяет размер файла истории и при необходимости восстанавливает его из резервной копии (в~/.zshrc)

if [ /home/my/zsh/hist/file -lt 64000 ]; then
    echo "History file is lower than 64 kbytes, restoring backup..."
    cp -f /mybackup/histfile /home/my/zsh/hist/file
fi

Ссылки

Дополнительная информация доступна по этому и этому вопросам.

9
28.04.2021, 23:22

Если еще не поздно ответить. Когда мой файл zhistory повреждается, это всегда происходит из-за внезапного завершения работы. Когда я перезагружаюсь, я просто редактирую файл ~/.zhistory и удаляю строку, которая явно будет повреждена. Обычно последняя строка, но иногда и предпоследняя. Тогда я в порядке. Мой файл zhistory весит почти 1 мегабайт и охватывает много лет.

2
28.04.2021, 23:22

Не думаю, что какая-либо опция zsh спасет ваше драгоценное .zsh_history.

Мой .zsh_historyбыл случайно усечен на протяжении многих лет, и я до сих пор не знаю, почему. Я перепробовал все варианты, которые смог найти на StackExchange, и, очевидно, попробовал конфигурацию из -моего -zsh.

Автоматическое резервное копирование

Чтобы не волноваться, когда в следующий раз моя история будет обрезана, я добавил эту строку вcrontab -e:

30 14 * * * cp /home/my_user/.zsh_history /backup/folder/zsh_history_$(date +\%Y_\%m_\%d).bak

Не стесняйтесь использовать anacron, rsyncили любой другой инструмент. Цель состоит в том, чтобы хранить коллекцию файлов .zsh_historyв безопасном месте, по крайней мере, в некоторых из них содержится нужная информация.

Восстановить историю

Когда вам нужно восстановить одну полную .zsh_historyиз ваших, возможно, усеченных резервных копий, вы можете использовать эту команду:

cat zsh_history*.bak | awk -v date="WILL_NOT_APPEAR$(date +"%s")" '{if (sub(/\\$/,date)) printf "%s", $0; else print $0}' | LC_ALL=C sort -u | awk -v date="WILL_NOT_APPEAR$(date +"%s")" '{gsub('date',"\\\n"); print $0}' >.merged_zsh_history

Который взят из этой превосходной статьи («Объединение файлов истории zsh»).

Он объединяет файлы истории, сортирует команды, удаляет дубликаты и не разбивает многострочные команды.

Несколько недель спустя

Как и планировалось, мой .zsh_historyбыл усечен без видимой причины.

Мои резервные копии работали нормально. Некоторые из них по-прежнему имели повторяющиеся команды в одних и тех же файлах. Приведенный выше awk-код распознает только точные дубликаты (time+duration+command )между файлами, но оставит их, если, например, lsбыл вызван в разное время. Итак, я написал этот небольшой скрипт на Ruby:

#! /usr/bin/env ruby
# Ruby script to merge zsh histories. In case of duplicates, it removes the old timestamps.
# It should do fine with multi-line commands.
# Make backups of your backups before running this script!
#
#./merge_zsh_histories.rb zsh_history_*.bak ~/.zsh_history > merged_zsh_history

MULTILINE_COMMAND = "TO_BE_REMOVED_#{Time.now.to_i}"

commands = Hash.new([0,0])

ARGV.sort.each do |hist|
  $stderr.puts "Parsing '#{hist}'"
  content = File.read(hist).gsub(/\\\n(?!:\s*\d{10,})/, MULTILINE_COMMAND)
  should_be_empty = content.each_line.grep_v(/^:/) + content.each_line.grep(/(?<!^): \d{10,}/)
  raise "Problem with those lines : #{should_be_empty}" unless should_be_empty.empty?
  content.each_line do |line|
    description, command = line.split(';', 2)
    _, time, duration = description.split(':').map(&:to_i)
    old_time, _old_duration = commands[command]
    if time > old_time
      commands[command] = [time, duration]
    end
  end
end

commands.sort_by{|_, time_duration| time_duration}.each{|command, (time, duration)|
  puts ':%11d:%d;%s' % [time, duration, command.gsub(MULTILINE_COMMAND, "\\\n")]
}

Он работал нормально и вернул правильный файл истории zsh _, который содержал все мои команды и был ненамного больше, чем самая большая резервная копия.

5
28.04.2021, 23:22

Я нашел альтернативное решение. :Я установил собственный инструмент истории команд.

Я использую McFly . Помимо удобных функций для более умного поиска по истории, ключ в этом контексте заключается в том, что для работы инструмент должен поддерживать свою собственную базу данных истории.

Augments your shell history to track command exit status, timestamp, and execution directory in a SQLite database.

Я надеюсь, что даже если мой .zsh_historyбудет продолжать повреждаться, база данных sqlite McFly останется в качестве подстраховки.

На самом деле, McFly автоматически обновляет .zsh_historyиз соображений совместимости, и до сих пор, примерно через полтора месяца, я не видел, чтобы он терял какие-либо данные. Файлы sqlite и .zsh_historyнеуклонно растут. Мой .zsh_historyсейчас 370К, что я считаю новым рекордом.

4
28.04.2021, 23:22

Теги

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