Bash 기록: 'ignoredups' 및 'erasedups' 설정이 세션 전체의 공통 기록과 충돌합니다.

Bash 기록: 'ignoredups' 및 'erasedups' 설정이 세션 전체의 공통 기록과 충돌합니다.

우선, 이것은 SE의 기존 스레드와 중복되지 않습니다. 나는 이 두 기사를 읽었습니다(처음,2위) 더 나은 bash 기록에 대해 설명했지만 답변 중 아무 것도 작동하지 않았습니다. btw, 저는 Fedora 15를 사용하고 있습니다.

내 사용자 디렉터리(/home/aahan/)의 파일 에 다음을 추가했지만 .bashrc작동하지 않았습니다. 누구든지 단서가 있습니까?

HISTCONTROL=ignoredups:erasedups  # no duplicate entries
HISTSIZE=1000                     # custom history size
HISTFILESIZE=100000                 # custom history file size
shopt -s histappend                      # append to history, don't overwrite it
PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"  # Save and reload the history after each command finishes

좋아, 이것이 내가 bash 기록에 원하는 것입니다(우선순위):

  • 중복된 항목은 저장되지 않으며 기존 항목은 모두 삭제됩니다.
  • 열려 있는 모든 터미널과 즉시 기록 공유
  • 덮어쓰는 대신 항상 기록을 추가하세요.
  • 여러 줄 명령을 단일 명령으로 저장(기본적으로 꺼져 있음)
  • 기본 기록 크기와 기록 파일 크기는 얼마입니까?

답변1

이것은 실제로 매우 흥미로운 행동이며 처음에는 문제를 크게 과소평가했음을 인정합니다. 하지만 먼저 사실은 다음과 같습니다.

1. 효과가 있는 것

이 기능은 다양한 방법으로 구현될 수 있지만 각 방법은 약간씩 다르게 작동합니다. 각 경우에 기록을 다른 터미널로 "전송"하려면(업데이트) Enter기록을 검색하려는 터미널을 눌러야 합니다.

  • 옵션 1:

     shopt -s histappend
     HISTCONTROL=ignoredups
     PROMPT_COMMAND="history -a; history -n; $PROMPT_COMMAND"
    

여기에는 두 가지 단점이 있습니다.

  1. 로그인(터미널 열기)할 때 기록 파일의 마지막 명령이 현재 터미널의 기록 버퍼로 두 번 읽혀집니다.
  2. 다른 터미널의 버퍼와 기록 파일은 동기화되지 않습니다.
  • 옵션 2:

     HISTCONTROL=ignoredups
     PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
    

(네, 필요 없어요 shopt -s histappend, 그렇죠~ 해야 하다 history -c중간 PROMPT_COMMAND) 이 버전에는 두 가지 중요한 단점도 있습니다.

  1. 기록 파일을 초기화해야 합니다. 그것은 포함해야합니다비어 있지 않은 줄이 하나 이상(무엇이든 될 수 있습니다).
  2. history명령은 잘못된 출력을 제공할 수 있습니다. 아래를 참조하세요.

[편집하다] "승자는..."

  • 옵션 3:

     HISTCONTROL=ignoredups:erasedups
     shopt -s histappend
     PROMPT_COMMAND="history -n; history -w; history -c; history -r; $PROMPT_COMMAND"
    

지금은. 그것은오직erasedups공유 내역 작업을 동시에 수행할 수 있는 옵션이 있습니다 .이것아마도마지막 해결책모든 문제를 해결하세요, 아한.


2. 왜 이런 일이 일어나는가?옵션 2작동하지 않는 것 같습니다(다음 중 하나:정확히 뭐야?예상대로 작동하지 않음)?

앞서 언급했듯이 위의 각 솔루션은 다르게 작동합니다. 하지만설정 작동 방식에 대한 가장 오해의 소지가 있는 설명은 history명령의 출력을 분석하는 것에서 비롯됩니다.. 대부분의 경우 명령을 내릴 수 있습니다.잘못된산출. 왜? 왜냐하면실행됐다앞으로! history에 포함된 다른 명령 시퀀스PROMPT_COMMAND.bash_history그러나 두 번째 또는 세 번째 옵션을 사용하면 콘텐츠 변경( watch -n1 "tail -n20 .bash_history"예: 사용량)을 모니터링하고 실제 기록이 무엇인지 확인할 수 있습니다 .

3. 왜옵션 3그렇게 복잡합니까?

그것은 모두 erasedups그것이 어떻게 작동하는지에 달려 있습니다. bash 매뉴얼에 따르면, "(...)는 erasedups해당 행을 저장하기 전에 현재 행과 일치하는 모든 이전 행을 기록 목록에서 삭제하게 합니다.". 이것이 실제로 OP가 원하는 것입니다(단지 예전에 생각했던 것처럼 반복이 없는 것만은 아니다.순서대로). 이것이 모든 history -.명령이 다음 위치에 있거나 있을 수 없는 이유입니다 PROMPT_COMMAND.

  • history -n 가지다history -w.bash_history다른 터미널에서 저장된 명령어를 읽기 전에,

  • history -w 가지다bash가 명령이 중복되었는지 확인한 후 새 기록을 파일에 저장합니다.

  • history -a 기필코 아니다대신 거기에 배치됩니다 history -w. 중복으로 확인되었는지 여부에 관계없이 파일에 새 명령이 추가되기 때문입니다.

  • history -c필요각 명령 후에 히스토리 버퍼가 파괴되는 것을 방지하기 때문에

  • history -r마지막으로필요파일에서 기록 버퍼를 복구하여 궁극적으로 터미널 세션 간에 기록을 공유할 수 있습니다.

이 솔루션은 다른 터미널의 모든 기록을 현재 터미널에 입력된 최신 명령 앞에 배치하여 기록 순서를 엉망으로 만듭니다. 또한 명령을 다시 입력하지 않는 한 기록 파일에 이미 있는 중복 행은 제거되지 않습니다.

답변2

프롬프트 명령에서는 스위치를 사용하고 있습니다 -c. 에서 man bash:

-씨   모든 항목을 삭제하여 기록 목록 지우기

열려 있는 모든 터미널과 기록을 공유하려면 다음을 사용할 수 있습니다 -n.

-N   기록 파일에서 읽지 않은 기록 행을 현재 기록 목록으로 읽어옵니다. 이는 현재 bash 세션이 시작된 이후 기록 파일에 추가된 줄입니다.

기본 크기는 설명서에도 나와 있습니다.

HISTSIZE 명령 기록에 기억할 명령 수입니다(아래 "기록" 참조). 기본값은 500입니다.

여러 줄 명령 저장:

이것CMDHIST쉘 옵션이 활성화되면 쉘은 여러 줄 명령의 각 줄을 동일한 기록 항목에 저장하려고 시도하며 필요한 경우 구문 정확성을 유지하기 위해 세미콜론을 추가합니다. 이것암석의shell 옵션을 사용하면 쉘이 세미콜론 대신 새 줄이 포함된 명령을 저장하게 됩니다.

또한 HIST* 명령을 앞에 추가해서는 안 됩니다 export. 이는 bash 전용 변수이지 환경 변수가 아닙니다. HISTCONTROL=ignoredups:erasedups그것으로 충분합니다.

답변3

종료 트랩과 함께 @rozcietrzewiacz의 옵션 3을 사용하면 터미널이 종료 시 수렴되는 자체 독립 기록 세션을 유지할 수 있습니다. 원격 홈 디렉토리를 잘 공유하는 서로 다른 시스템에서 여러 세션을 처리하는 것 같습니다.

export HISTSIZE=5000
export HISTFILESIZE=5000
export HISTCONTROL=ignorespace:erasedups
shopt -s histappend
function historymerge {
    history -n; history -w; history -c; history -r;
}
trap historymerge EXIT
PROMPT_COMMAND="history -a; $PROMPT_COMMAND"
  • historymerge함수는 기록 파일에서 세션 행을 로드하고, 이를 세션 기록과 결합하고, 중복 제거를 통해 새 기록 파일을 작성한 다음(이에 따라 이전에 추가된 중복 행을 압축함) 기록을 다시 로드합니다.

  • 힌트를 보존하면 history -a각 명령을 중복 제거하지 않고 기록 파일을 업데이트하므로 기록 손실 가능성이 최소화됩니다.

  • 마지막으로 세션이 닫힐 때 트랩이 historymerge실행되어 최신 정리 기록 파일을 가져옵니다. 여기서 가장 최근에 닫힌 세션에 대한 명령이 파일 끝까지 표시됩니다.

이러한 방식으로 각 터미널 세션은 시작된 시점부터 자체적인 독립적인 기록을 갖습니다. 나는 다른 작업을 위해 다른 터미널을 여는 경향이 있기 때문에 이것이 더 유용하다고 생각합니다(따라서 각 터미널에서 다른 명령을 반복하고 싶습니다). 다행스럽게도 여러 터미널이 지속적으로 재동기화를 시도하는 방법을 이해하는 것보다 훨씬 간단합니다.이미 주문함historymerge내역은 분산 방식으로 기록됩니다( 의도적으로 세션 또는 모든 세션을 선택하기 위해 이 기능을 사용할 수도 있음 ).

필요한 기록 길이를 수용할 수 있을 만큼 크기 제한이 커야 합니다.추가하다동시에 활성화된 모든 세션에 의해 추가될 수 있는 중복 제거되지 않은 행의 수입니다. HISTIGNORE가치가 낮은 정크 명령을 필터링하는 데 널리 사용된 덕분에 5000이면 충분합니다 .

답변4

첫 번째 추가 에서는 다음을 수행합니다 .bashrc.

HISTCONTROL='erasedups'

그런 다음 다음 기록 정리 도우미 기능을 추가합니다(중복 항목이 제거됨).

clean_bash_history_file() {
  bash_history_file=$(mktemp "$USER"_bash_historyXXXXXX)
  awk 'NR == FNR { a[$0]++; next; }; ++b[$0] == a[$0]' \
      "$HOME/.bash_history" "$HOME/.bash_history" > "$bash_history_file"
  mv "$bash_history_file" "$HOME/.bash_history"
  unset bash_history_file
}

그런 다음 다음 기록 업데이트 기능을 만듭니다.

update_history() {   
    history -a
    clean_bash_history_file
    history -c
    history -r
}

마지막으로 추가됨

PROMPT_COMMAND=update_history

이렇게 하면 올바른 기록 순서가 유지되고 모든 중복 항목이 제거됩니다.

또한 .HISTFILESIZE​ 귀하의 폴더에도 있는지 HISTSIZE확인하세요.shopt -s histappend.bashrc

관련 정보