배쉬 히스토리 : "무시 된"및 "삭제 된"설정은 세션 간 공통 히스토리와 충돌합니다.


84

우선, 이것은 SE의 기존 스레드와 중복되지 않습니다. 더 나은 bash 기록 에서이 두 스레드 ( 1 , 2 )를 읽었 지만 답변이 없습니다.-Fedora 15에 있습니다.

.bashrc사용자 디렉토리 (/ home / aahan /) 의 파일에 다음을 추가 했는데 작동하지 않습니다. 누구나 실마리가 있습니까?

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 기록 (우선 순위)으로 원하는 것입니다.

  • 사본을 저장하지 않고 기존 사본을 지우십시오.
  • 열려있는 모든 터미널과 즉시 내역 공유
  • 덮어 쓰지 말고 항상 기록을 추가하십시오.
  • 여러 줄 명령을 단일 명령으로 저장 (기본적으로 꺼져 있음)
  • 기본 기록 크기와 기록 파일 크기는 얼마입니까?

충돌! 누군가? 아무것도 작동하지 않습니다. Fedora 15 (Gnome 3에서 Windows 호스트 가상 머신에서 실행 중)에 문제가 될 수 있습니까?
its_me

여기에 게시물을 "충돌"하지 마십시오. 그들이 대답을 얻지 못하면 더 명확하게 질문하고, 상황에 맞는 단서 등을 포함시켜야합니다. 게시물에주의가 필요한 경우 더 많은 사람들이 더 많은주의를 기울 이도록하는 현상금을 발행 할 수 있습니다.
Caleb

1
bash를 사용하고 있습니까? ( echo $SHELL). 열린 쉘에서 수동으로 설정을 실행하면 설정이 작동합니까? 분명히 그들은 많은 다른 사람들을 위해 일하기 때문에 설정이 옳습니다. 실제로 잘못 구현하고 있습니다. 그리고 Fedora15 / Gnome3 / 가상 머신은 실제 기능과 거의 관련이 없습니다 bash.
Caleb

@Caleb, 먼저 게시물을 부딪 쳐서 죄송합니다. 또한, 나는 최선을 다해 매우 명확하게 노력했습니다. 아니요, 쉘에서 발행하지 않았습니다. 방금 .bashrc파일에 복사하여 붙여 넣었습니다 . 그게 잘못이야? 실제 쉘 명령으로이 게시물에 "답변"을 추가 할 수 있습니까? (내 멍청한 놈을 참아주세요.)
its_me

1
스크립트로 작성하거나 .bashrc실제 쉘 명령입니다. 스크립트는 일련의 쉘 명령입니다. 또한 최근에 export비트를 제거 한 편집 은 좋지 않은 생각이었습니다.
Caleb

답변:


119

이것은 실제로 매우 흥미로운 행동이며 처음에 질문을 크게 과소 평가했다고 고백합니다. 그러나 먼저 사실 :

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 파일과 중복을 삭제하는 기록을 저장하기 위해 거기에있을,

  • history -a history -w중복 지우기를 트리거하지 않기 때문에에 대신 배치 해서는 안됩니다 .

  • history -c또한 필요 가 각 명령 후에 기록 버퍼를 부수고 방지하기 때문에,

  • 마지막으로, history -r되어 필요에 따라서 마지막으로 터미널 세션에서 공유 역사를 만드는 파일에서 기록 버퍼를 복원 할 수 있습니다.


2
"하지만 히스토리 명령의 출력 분석에서 설정 작동 방식에 대한 가장 오해의 소지가 있습니다." 이것이 이것이 OP 문제의 핵심이라고 생각합니다. 탁월한 추론.
jasonwryan

2
나는 마침내 당신의 요점을 보았다. '중복'함으로써 당신은 나 자신 이외의 것을 의미했습니다. 나는 같은 명령의 순서 에만 집중했다 . 답변이 업데이트되었습니다- "옵션 3"을 참조하십시오. 또한 귀하의 경우 기록이 어떻게 작동하는지 테스트하려면 실제로 watch "tail -n 20 .bash_history"대신 사용해야 합니다 tail -f .bash_history.
rozcietrzewiacz

2
옵션 3은 (bash는이 3.2.25 (1) -release) :( 역사 내 10 만 개 라인을 모두 전멸
펠리페 알바레즈

2
history -c각 명령 후에 히스토리 버퍼를 휴지통에 버리지 못하도록하기 때문에이 휴지통이 발생하는 이유는 무엇입니까?
Piotr Dobrogost

2
실제로 솔루션 3이 작동하지 않습니다. 매우 버그가 많으며 사용자가 다른 터미널에서 입력하는 순서에 따라 다릅니다. 특히 터미널 간을 전환 할 때 명령이 손실 될 수 있습니다. 출처 : 시도했습니다.
6cef

8

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

-c   모든 항목을 삭제하여 기록 목록을 지 웁니다.

모든 열린 터미널과 역사를 공유하려면 다음을 사용하십시오 -n.

-n   히스토리 파일에서 아직 읽지 않은 히스토리 라인을 현재 히스토리 목록으로 읽습니다. 이것은 현재 bash 세션이 시작된 이후 히스토리 파일에 추가 된 행입니다.

기본 크기는 다음 매뉴얼에도 있습니다.

HISTSIZE 명령 기록에서 기억해야하는 명령의 수입니다 (아래 기록 참조). 기본값은 500입니다.

여러 줄 명령을 저장하려면

cmdhist의 쉘 옵션이 활성화 된 경우, 구문 정확성을 유지하기 위해 필요한 세미콜론을 추가, 같은 역사 항목에 여러 줄의 명령의 각 라인을 저장하려고하는 쉘됩니다. lithist의 쉘 옵션이 포함 된 줄 바꿈 대신 세미콜론으로 명령을 저장하려면 쉘을 발생합니다.

또한 HIST * 명령을 export환경 변수 HISTCONTROL=ignoredups:erasedups가 아닌 bash 전용 변수로 시작하면 안됩니다 . 충분합니다.


이것이 export PROMPT_COMMAND="history -a; history -n; history -r; $PROMPT_COMMAND"맞습니까? 또한 히스토리 파일에 여러 줄 명령을 단일 명령으로 저장하는 방법을 알고 있습니까 (기본적으로 꺼져 있음)?
its_me

1
예. 위에서 인용 한 맨 페이지에 따라 shopt -s cmdhist여러 줄을 저장합니다.
jasonwryan

알았어, 나는 모두 시도했다. HISTCONTROL=ignoredups:erasedups작동하지 않는 것 같습니다 . 또한 .bashrc파일에서 사용자 정의 함수 중 하나만 사용 하려고했습니다 . 무엇이 잘못 될 수 있는지 아십니까? 가상 머신--Windows 7 호스트에서 Fedora 15를 사용하고 있습니다.
its_me

다른 시작 파일 (예 /etc/bashrc: .bash_profile등)을 덮어 쓰는 파일이 없는지 확인하십시오 .
jasonwryan

.bash_profile파일에 문제가 없습니다. /etc/bashrc여기에 넣은 내용은 pastebin.com/Uae6sE6s
its_me

8

이것이 내가 생각 해낸 것이며 지금까지는 만족합니다…

alias hfix='history -n && history | sort -k2 -k1nr | uniq -f1 | sort -n | cut -c8- > ~/.tmp$$ && history -c && history -r ~/.tmp$$ && history -w && rm ~/.tmp$$'  
HISTCONTROL=ignorespace  
shopt -s histappend  
shopt -s extglob  
HISTSIZE=1000  
HISTFILESIZE=2000  
export HISTIGNORE="!(+(*\ *))"  
PROMPT_COMMAND="hfix; $PROMPT_COMMAND" 

노트:

  • 예, 복잡합니다 ...하지만 모든 중복을 제거하면서 각 터미널 내에서 연대기를 유지합니다!
  • My HISTIGNORE는 인수가없는 모든 명령을 무시합니다. 이것은 일부 사람들에게는 바람직하지 않으며 생략 될 수 있습니다.

1

대신 이것을 사용하십시오 :

HISTCONTROL=ignoreboth

0

다음을 잊었 기 때문에 작동하지 않습니다.

 -n   read all history lines not already read from the history file
      and append them to the history list

그러나 실제로 history -n는 버그가있는 것 같습니다 export HISTCONTROL=ignoreboth:erasedups.

실험하자 :

$ PROMPT_COMMAND=
$ export HISTCONTROL=ignoreboth:erasedups
$ export HISTFILE=~/.bash_myhistory
$ HISTIGNORE='history:history -w'
$ history -c
$ history -w

여기서 우리는 딥 지우기를 켜고, 히스토리를 커스텀 파일로 전환하고, 히스토리를 지 웁니다. 모든 명령이 완료되면 빈 기록 파일과 현재 기록에 하나의 명령이 있습니다.

$ history
$ cat ~/.bash_myhistory
$ history
$ 1  [2019-06-17 14:57:19] cat ~/.bash_myhistory

두 번째 터미널을 열고 6 개의 명령도 실행하십시오. 그 후 :

$ echo "X"
$ echo "Y"
$ history -w
$ history
  1  [2019-06-17 15:00:21] echo "X"
  2  [2019-06-17 15:00:23] echo "Y"

이제 현재 기록에는 두 가지 명령이 있으며 기록 파일에는 다음이 있습니다.

#1560772821
echo "X"
#1560772823
echo "Y"

첫 번째 터미널로 돌아 가기 :

$ history -n
$ history
1  [2019-06-17 14:57:19] cat ~/.bash_myhistory 
2  [2019-06-17 15:03:12] history -n

어 ... 어떤 echo명령도 읽을 수 없습니다. 두 번째 터미널로 다시 전환하고 다음을 수행하십시오.

$ echo "Z"
$ history -w

이제 히스토리 파일은 다음과 같습니다.

#1560772821
echo "X"
#1560772823
echo "Y"
#1560773057
echo "Z"

첫 번째 터미널로 다시 전환하십시오.

$ history -n
$ history
  1  [2019-06-17 14:57:19] cat ~/.bash_myhistory 
  2  [2019-06-17 15:03:12] history -n
echo "Z"

echo "Z"명령이에 병합 되었음을 알 수 있습니다 history -n.

또 다른 버그 는 명령 시간이 아닌 명령 번호로 기록에서 명령을 읽었 기 때문이라고 생각합니다. 나는 다른 echo명령이 역사에 나타 났을 것으로 기대한다


0

삭제 된 부분은 선행 및 후행 공백을 자르지 않습니다 (일부 언어에서는 mp 프처럼). 이것은 버그입니다. 또한 삭제 된 항목이 이전 항목을 모두 삭제하지는 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.