자동 백업

자동 백업

가끔씩 내 zsh기록이 잘린 것을 발견하고(또는 완전히 손실되었을 수도 있고 말하기 어렵습니다) 백업에서 복원해야 합니다.

예를 들어 오늘은 다음과 같습니다.

ls -lh ~/.zsh_history
-rw-------  1 stripe  staff    32K 21 Feb 10:20 /Users/stripe/.zsh_history

하지만 며칠 전 백업에서는 다음과 같습니다.

-rw-------@  1 stripe  staff  203K 17 Feb 22:36 /Volumes/Time Machine Backups/.../Users/stripe/.zsh_history

zsh많은 기록을 저장하도록 구성했으므로 이는 셸이 의도적으로 파일을 자르는 데 문제가 되지 않습니다.

unsetopt share_history
setopt inc_append_history
setopt hist_ignore_all_dups
HISTSIZE=500000
SAVEHIST=$HISTSIZE

다른 사람이 이것을 경험하고 이를 완화할 방법을 찾았습니까? zsh제가 모르는 봄맞이 대청소 기능이 있나요 ?

답변1

ZTE

여러 가지 이유로 기록 파일이 잘리거나, 유실되거나, 지워질 수 있습니다. 그 이유는 다음과 같습니다.

  • zsh 기록 파일 손상(셸을 열 때 정전/시스템 오류로 인해, 이 경우 시스템 오류 시 실행되도록 fsck를 설정해야 함)
  • Zsh 구성 파일이 로드되지 않았습니다(예: $HOMEenv 변수가 정의되지 않은 경우)
  • 지원하지 않음역사 기록 보관소에 있는 사람들zsh 재설정 기록을 만들 수 있습니다
  • 표백제 등 청소 도구
  • Zsh 구성 오류
  • 쉘 간 공유에는 $HISTFILE더 엄격한 제한이 있습니다 $HISTSIZE. 예를 들어 $HISTFILEbashrc 없이 zsh에서 bash 쉘을 실행하는 경우 하위 쉘은 zsh에서 상속된 변수를 사용하고 $HISTSIZEbashrc 변수에 정의된 변수를 적용합니다.
  • 등.

노트

과거 사용 가능한 설정 옵션

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

링크

추가 정보는 다음에서 확인할 수 있습니다.이것그리고이것질문.

답변2

난 그렇게 생각하지 않아어느zsh 옵션은 소중한 .zsh_history.

내 것은 .zsh_history몇 년 동안 무작위로 잘렸는데 아직도 이유를 모르겠습니다. StackExchange에서 찾을 수 있는 모든 옵션을 시도했고 분명히 oh-my-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

모두 이 훌륭한 곳에서 왔습니다.Article("zsh 기록 파일 결합").

기록 파일을 병합하고, 명령을 정렬하고, 중복 항목을 제거하고, 여러 줄 명령을 중단하지 않습니다.

몇 주 후에

예정대로 내 콘텐츠가 .zsh_history뚜렷한 이유 없이 차단되었습니다.

내 백업이 제대로 작동합니다. 그들 중 일부는 여전히 동일한 파일에 중복된 명령을 가지고 있습니다. 위의 awk 코드는 파일 간의 정확한 중복(시간+지속 시간+명령)만 식별하지만 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)
  content.scrub!("#")
  content.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_history 파일을 반환합니다.

답변3

대체 솔루션을 찾았습니다. 사용자 지정 명령 기록 도구를 설치했습니다.

나는 그것을 사용하고 있다맥플라이. 보다 스마트한 기록 검색을 위한 깔끔한 기능 외에도 이 경우의 핵심은 도구가 작동하려면 자체 기록 데이터베이스를 유지해야 한다는 것입니다.

SQLite 데이터베이스에서 명령 종료 상태, 타임스탬프 및 실행 디렉터리를 추적하도록 셸 기록을 향상합니다.

내 희망은 내 데이터베이스가 .zsh_history계속 손상되더라도 McFly의 sqlite 데이터베이스가 여전히 내 뒤를 지켜줄 것이라는 것입니다.

실제로 .zsh_historyMcFly는 호환성상의 이유로 자동으로 업데이트되며 약 한 달 반이 지난 지금까지 데이터가 손실되는 것을 본 적이 없습니다. sqlite와 .zsh_history파일 모두 꾸준히 증가하고 있습니다. 나는 .zsh_history지금 370K에 도달했는데, 이는 새로운 기록이라고 생각합니다.

답변4

답변주시면 늦지 않습니다. 내 zhistory 파일이 손상되면 항상 갑작스러운 종료로 인해 발생합니다. 재부팅할 때 ~/.zhistory 파일을 편집하고 눈에 띄게 끊어진 줄을 제거했습니다. 일반적으로 마지막 줄이지만 때로는 마지막 줄에서 두 번째까지입니다. 그러면 나는 괜찮을 것이다. 내 zhistory 파일은 거의 1meg이며 수년에 걸쳐 있습니다.

관련 정보