it-swarm-ko.tech

여러 터미널 창에서 bash 기록 유지

일관되게 둘 이상의 터미널이 열려 있습니다. 다양한 비트와 밥을하는 2에서 10 사이. 이제 다시 시작하고 다른 터미널 세트를 연다 고 가정 해 봅시다. 어떤 사람들은 특정한 것을 기억하고 어떤 사람들은 잊어 버립니다.

나는 다음과 같은 역사를 원한다.

  • 모든 터미널에서 모든 것을 기억
  • 모든 터미널에서 즉시 액세스 할 수 있습니다 (예 : 하나의 ls, 이미 실행중인 다른 터미널로 전환 한 다음 위로 누르면 ls이 표시됨)
  • 명령 앞에 공백이 있으면 명령을 잊지 않습니다.

배쉬가 그렇게 작동하도록 할 수있는 일이 있습니까?

565
Oli

~/.bashrc에 다음을 추가하십시오

# Avoid duplicates
HISTCONTROL=ignoredups:erasedups  
# When the Shell exits, append to the history file instead of overwriting it
shopt -s histappend

# After each command, append to the history file and reread it
Prompt_COMMAND="${Prompt_COMMAND:+$Prompt_COMMAND$'\n'}history -a; history -c; history -r"
355
Pablo R.

그래서 이것은 내 모든 역사 관련 .bashrc 것입니다.

export HISTCONTROL=ignoredups:erasedups  # no duplicate entries
export HISTSIZE=100000                   # big big history
export HISTFILESIZE=100000               # big big history
shopt -s histappend                      # append to history, don't overwrite it

# Save and reload the history after each command finishes
export Prompt_COMMAND="history -a; history -c; history -r; $Prompt_COMMAND"

Mac OS X 10.5의 bash 3.2.17, 10.6의 bash 4.1.7로 테스트되었습니다.

257
kch

Bash 세션 히스토리 공유에 대한 나의 시도는 다음과 같습니다. 이를 통해 히스토리 카운터가 섞이지 않고 !number와 같은 히스토리 확장이 작동하는 방식으로 bash 세션간에 히스토리 공유가 가능합니다 (일부 제한 사항이 있음).

Ubuntu 10.04 LTS (Lucid Lynx)에서 Bash 버전 4.1.5 사용.

HISTSIZE=9000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups

_bash_history_sync() {
    builtin history -a         #1
    HISTFILESIZE=$HISTSIZE     #2
    builtin history -c         #3
    builtin history -r         #4
}

history() {                  #5
    _bash_history_sync
    builtin history "[email protected]"
}

Prompt_COMMAND=_bash_history_sync

설명:

  1. 방금 입력 한 줄을 $HISTFILE에 추가하십시오 (기본값은 .bash_history). 이로 인해 $HISTFILE가 한 줄씩 증가합니다.

  2. 특수 변수 $HISTFILESIZE를 특정 값으로 설정하면 가장 오래된 항목을 제거하여 Bash가 $HISTFILE 줄을 $HISTFILESIZE 줄보다 길지 않게됩니다.

  3. 실행중인 세션 기록을 지우십시오. 이것은 $HISTSIZE만큼 이력 카운터를 줄입니다.

  4. $HISTFILE의 내용을 읽고 현재 실행중인 세션 기록에 삽입하십시오. $HISTFILE의 행 수만큼 히스토리 카운터가 증가합니다. $HISTFILE의 줄 수는 반드시 $HISTFILESIZE 일 필요는 없습니다.

  5. history() 함수는 내장 히스토리를 대체하여 히스토리가 표시되기 전에 동기화되었는지 확인합니다. 이것은 숫자로 히스토리 확장에 필요합니다 (자세한 내용은 나중에 참조).

자세한 설명 :

  • 1 단계는 현재 실행중인 세션의 명령이 글로벌 히스토리 파일에 기록되도록합니다.

  • 4 단계는 다른 세션의 명령이 현재 세션 히스토리로 읽히도록합니다.

  • 4 단계는 기록 카운터를 높이기 때문에 어떤 방식 으로든 카운터를 줄여야합니다. 이것은 3 단계에서 수행됩니다.

  • 3 단계에서 히스토리 카운터는 $HISTSIZE만큼 줄어 듭니다. 4 단계에서 히스토리 카운터는 $HISTFILE의 행 수만큼 증가합니다. 2 단계에서 $HISTFILE의 행 수가 정확히 $HISTSIZE인지 확인합니다 (이는 $HISTFILESIZE$HISTSIZE와 같아야 함을 의미합니다).

히스토리 확장의 제한 조건 정보 :

숫자로 히스토리 확장을 사용하는 경우 always 사용하기 전에 즉시 숫자를 찾아야합니다. 즉, 번호 조회와 사용 사이에 bash 프롬프트가 표시되지 않습니다. 그것은 일반적으로 enter와 ctrl + c가 없음을 의미합니다.

일반적으로 Bash 세션이 둘 이상 있으면 번호 별 히스토리 확장이 두 개의 Bash Prompt 디스플레이간에 값을 유지한다는 보장은 없습니다. Prompt_COMMAND가 실행될 때 다른 모든 Bash 세션의 기록이 현재 세션의 기록에 통합되기 때문입니다. 다른 bash 세션에 새 명령이 있으면 현재 세션의 기록 번호가 달라집니다.

나는이 제약이 합리적이라고 생각한다. 임의의 이력 번호를 기억할 수 없으므로 어쨌든 매번 번호를 찾아야합니다.

일반적으로 이처럼 숫자로 기록 확장을 사용합니다

$ history | grep something #note number
$ !number

다음 Bash 옵션을 사용하는 것이 좋습니다.

## reedit a history substitution line if it failed
shopt -s histreedit
## edit a recalled history line before executing
shopt -s histverify

이상한 버그 :

히스토리 명령을 파이프로 실행하면 해당 명령이 히스토리에 두 번 나열됩니다. 예를 들면 다음과 같습니다.

$ history | head
$ history | tail
$ history | grep foo
$ history | true
$ history | false

모든 기록에 두 번 나열됩니다. 왜 그런지 모르겠습니다.

개선을위한 아이디어 :

  • _bash_history_sync() 함수가 매번 실행되지 않도록 수정하십시오. 예를 들어 프롬프트에서 CTRL+C 다음에 실행하면 안됩니다. 나는 종종 그 줄을 실행하고 싶지 않다고 결정할 때 긴 명령 줄을 폐기하기 위해 CTRL+C를 사용합니다. 때로는 Bash 완료 스크립트를 중지하기 위해 CTRL+C를 사용해야합니다.

  • 현재 세션의 명령은 항상 현재 세션 기록에서 가장 최신이어야합니다. 이것은 또한 주어진 이력 번호가이 세션의 이력 항목 값을 유지한다는 부작용이 있습니다.

123
lesmana

bash를 사용하는 방법을 모르겠습니다. 그러나 zsh 의 가장 인기있는 기능 중 하나입니다.
개인적으로 zsh보다 bash를 선호하므로 시도해 보는 것이 좋습니다.

역사를 다루는 .zshrc 부분은 다음과 같습니다.

SAVEHIST=10000 # Number of entries
HISTSIZE=10000
HISTFILE=~/.zsh/history # File
setopt APPEND_HISTORY # Don't erase history
setopt EXTENDED_HISTORY # Add additional data to history like timestamp
setopt INC_APPEND_HISTORY # Add immediately
setopt HIST_FIND_NO_DUPS # Don't show duplicates in search
setopt HIST_IGNORE_SPACE # Don't preserve spaces. You may want to turn it off
setopt NO_HIST_BEEP # Don't beep
setopt SHARE_HISTORY # Share history between session/terminals
45
Maciej Piechotka

이렇게하려면 ~/.bashrc에 두 줄을 추가해야합니다.

shopt -s histappend
Prompt_COMMAND="history -a;history -c;history -r;$Prompt_COMMAND"

man bash에서 :

Histappend Shell 옵션이 활성화 된 경우 (아래의 Shell BUILTIN COMMANDS 아래에서 shopt 설명 참조) 행이 내역 파일에 추가되고, 그렇지 않으면 내역 파일을 덮어 씁니다.

17
Chris Down

Muerr가 제안한 "history -a"및 "history -r"을 실행하도록 BASH 프롬프트를 편집 할 수 있습니다.

savePS1=$PS1

(당신이 무언가를 엉망으로 만드는 경우가 거의 보장됩니다)

PS1=$savePS1`history -a;history -r`

(이것은 백틱입니다. 모든 프롬프트에서 history -a 및 history -r을 실행합니다. 텍스트가 출력되지 않으므로 프롬프트가 변경되지 않습니다.

PS1 변수를 원하는 방식으로 설정했으면 ~/.bashrc 파일에 영구적으로 설정하십시오.

테스트하는 동안 원래 프롬프트로 돌아가려면 다음을 수행하십시오.

PS1=$savePS1

나는 이것에 대해 기본적인 테스트를 수행하여 일종의 작동하는지 확인했지만 모든 프롬프트에서 history -a;history -r를 실행하는 부작용에 대해서는 말할 수 없습니다.

11
Schof

아래 문제를 해결하는 bash 또는 zsh 기록 동기화 솔루션이 필요한 경우 http://ptspts.blogspot.com/2011/03/how-to-automatically-synchronize-Shell.html에서 참조하십시오.

문제는 다음과 같습니다. 두 개의 셸 창 A와 B가 있습니다. 셸 창 A에서 sleep 9999를 실행하고 셸 창 B에서 절전 모드가 완료 될 때까지 기다리지 않고 bash 기록에서 sleep 9999를 참조하십시오.

여기에서 대부분의 다른 솔루션이이 문제를 해결하지 못하는 이유는 Prompt_COMMAND 또는 PS1를 사용하여 기록 변경 내용을 기록 파일에 기록하고 있기 때문에 둘 다 너무 늦게 실행되고 있기 때문입니다. sleep 9999 명령이 완료된 후.

10
pts

맞아, 결국 이것은 괜찮은 해결책을 찾기 위해 짜증을 냈습니다.

# Write history after each command
_bash_history_append() {
    builtin history -a
}
Prompt_COMMAND="_bash_history_append; $Prompt_COMMAND"

이것이하는 일은이 스레드에서 말한 것에 대한 일종의 융합입니다. 단, 모든 명령 후에 왜 세계 역사를 다시로드 할 것인지 이해할 수 없습니다. 다른 터미널에서 일어나는 일에 대해서는 거의 신경 쓰지 않지만 항상 한 터미널에서 일련의 명령을 실행합니다.

make
ls -lh target/*.foo
scp target/artifact.foo vm:~/

(간단한 예)

그리고 또 다른 :

pv ~/test.data | nc vm:5000 >> output
less output
mv output output.backup1

어떤 방법으로도 명령을 공유하고 싶지 않습니다.

9
Yarek T

당신이 사용할 수있는 history -a 현재 세션 기록을 histfile에 추가 한 다음 history -r 다른 터미널에서 histfile을 읽으십시오.

9
jtimberman

내가 사용하는 대안이 있습니다. 번거롭지 만 때로는 @axel_c가 각 터미널에 별도의 기록 인스턴스를 만들고 싶을 수도있는 문제를 해결합니다 (하나는 모니터링, 하나는 vim 등).

지속적으로 업데이트하는 별도의 추가 기록 파일을 보관합니다. 다음은 핫키에 매핑되었습니다.

history | grep -v history >> ~/master_history.txt

이것은 현재 터미널의 모든 히스토리를 홈 디렉토리의 master_history.txt 파일에 추가합니다.

마스터 히스토리 파일을 검색하는 별도의 단축키가 있습니다.

cat /home/toby/master_history.txt | grep -i

나는 고양이를 사용한다 | grep은 정규식에 들어가기 위해 커서를 끝에 둡니다. 덜 추한 방법은이 작업을 수행하기 위해 경로에 몇 가지 스크립트를 추가하는 것이지만 단축키는 내 목적으로 작동합니다. 또한 정기적으로 작업 한 다른 호스트에서 내역을 가져 와서 해당 내역을 master_history.txt 파일에 추가합니다.

사용했던 까다로운 정규 표현식이나 7 개월 전에 생각해 낸 이상한 Perl one-liner를 빠르게 검색하고 찾을 수 있다는 것은 항상 좋은 일입니다.

8
Toby

마지막 수정 사항을 제공 할 수 있습니다. env 변수 HISTCONTROL이 "ignorespace"(또는 "ignoreboth")를 지정하지 않았는지 확인하십시오.

그러나 여러 동시 세션으로 고통을 느낍니다. bash에서는 단순히 잘 처리되지 않습니다.

7
jmanning2k

@lesmana의 answer 에 대한 개선 사항은 다음과 같습니다. 가장 큰 차이점은 동시 창은 기록을 공유하지 않는다는 것입니다. 즉, 다른 윈도우의 컨텍스트를 현재 윈도우에로드하지 않고도 윈도우에서 계속 작업 할 수 있습니다.

'history'를 명시 적으로 입력하면 OR 새 창을 열면 이전의 모든 창에서 이력을 얻습니다.

또한 이 전략 을 사용하여 컴퓨터에 입력 한 모든 명령을 보관합니다.

# Consistent and forever bash history
HISTSIZE=100000
HISTFILESIZE=$HISTSIZE
HISTCONTROL=ignorespace:ignoredups

_bash_history_sync() {
  builtin history -a         #1
  HISTFILESIZE=$HISTSIZE     #2
}

_bash_history_sync_and_reload() {
  builtin history -a         #1
  HISTFILESIZE=$HISTSIZE     #2
  builtin history -c         #3
  builtin history -r         #4
}

history() {                  #5
  _bash_history_sync_and_reload
  builtin history "[email protected]"
}

export HISTTIMEFORMAT="%y/%m/%d %H:%M:%S   "
Prompt_COMMAND='history 1 >> ${HOME}/.bash_eternal_history'
Prompt_COMMAND=_bash_history_sync;$Prompt_COMMAND
7
rouble

여러 사람이 동일한 서버에서 작업 할 수 있으므로 기록을 tty 당 파일에 넣기로 결정했습니다. 각 세션의 명령을 분리하면 감사하기가 더 쉽습니다.

# Convert /dev/nnn/X or /dev/nnnX to "nnnX"
HISTSUFFIX=`tty | sed 's/\///g;s/^dev//g'`
# History file is now .bash_history_pts0
HISTFILE=".bash_history_$HISTSUFFIX"
HISTTIMEFORMAT="%y-%m-%d %H:%M:%S "
HISTCONTROL=ignoredups:ignorespace
shopt -s histappend
HISTSIZE=1000
HISTFILESIZE=5000

역사는 이제 다음과 같습니다 :

[email protected]:~# test 123
[email protected]:~# test 5451
[email protected]:~# history
1  15-08-11 10:09:58 test 123
2  15-08-11 10:10:00 test 5451
3  15-08-11 10:10:02 history

파일은 다음과 같습니다.

[email protected]:~# ls -la .bash*
-rw------- 1 root root  4275 Aug 11 09:42 .bash_history_pts0
-rw------- 1 root root    75 Aug 11 09:49 .bash_history_pts1
-rw-r--r-- 1 root root  3120 Aug 11 10:09 .bashrc
6
Litch

여기서 나는 하나의 문제를 지적 할 것이다.

export Prompt_COMMAND="${Prompt_COMMAND:+$Prompt_COMMAND$'\n'}history -a; history -c; history -r"

Prompt_COMMAND="$Prompt_COMMAND;history -a; history -n"

Source ~/.bashrc를 실행하면 $ Prompt_COMMAND는 다음과 같습니다.

"history -a; history -c; history -r history -a; history -c; history -r"

"history -a; history -n history -a; history -n"

이 반복은 'source ~/.bashrc'를 실행할 때마다 발생합니다. 'echo $ Prompt_COMMAND'를 실행하여 'source ~/.bashrc'를 실행할 때마다 Prompt_COMMAND를 확인할 수 있습니다.

"history -n history -a"와 같은 일부 명령이 깨져있는 것을 볼 수 있습니다. 그러나 좋은 소식은 다른 부분은 여전히 ​​유효한 명령 시퀀스를 형성하기 때문에 여전히 작동한다는 것입니다.

개인적으로 나는 다음과 같은 간단한 버전을 사용합니다.

shopt -s histappend
Prompt_COMMAND="history -a; history -c; history -r"

위에 언급 된 것과 같은 문제는 없지만 대부분의 기능을 가지고 있습니다.

또 다른 요점은 다음과 같습니다. 정말 마법이 없습니다 . Prompt_COMMAND는 단순한 bash 환경 변수입니다. 이 명령은 bash Prompt ($ 기호)를 받기 전에 실행됩니다. 예를 들어, Prompt_COMMAND는 "echo 123"이고 터미널에서 "ls"를 실행합니다. 효과는 "ls; echo 123"을 실행하는 것과 같습니다.

$ Prompt_COMMAND="echo 123"

출력 ( 'Prompt_COMMAND = "echo 123"; $ Prompt_COMMAND'실행과 동일) :

123

다음을 실행하십시오.

$ echo 3

산출:

3
123

"history -a"는 메모리의 히스토리 명령을 ~/.bash_history에 쓰는 데 사용됩니다.

"history -c"는 메모리에서 히스토리 명령을 지우는 데 사용됩니다.

"history -r"은 ~/.bash_history에서 메모리로 기록 명령을 읽는 데 사용됩니다.

역사 명령 설명을 참조하십시오 : http://ss64.com/bash/history.html

추신 : 다른 사용자가 지적했듯이 export 는 불필요합니다. 참조 : . bashrc에서 내보내기 사용

5
fstang

세션 또는 작업별로 내역 파일을 설정하는 스크립트를 작성하여 다음을 기반으로합니다.

        # write existing history to the old file
        history -a

        # set new historyfile
        export HISTFILE="$1"
        export HISET=$1

        # touch the new file to make sure it exists
        touch $HISTFILE
        # load new history file
        history -r $HISTFILE

모든 기록 명령을 저장할 필요는 없지만 내가 관심있는 명령을 저장하고 검색하기가 더 쉬워 모든 명령을 통과합니다. 내 버전에는 모든 기록 파일이 나열되어 있으며 모든 기록 파일을 검색하는 기능이 있습니다.

전체 소스 : https://github.com/simotek/scripts-config/blob/master/hiset.sh

3
simotek

다음은 does n't 개별 세션에서 기록을 혼합하는 솔루션입니다!

기본적으로 각 세션의 기록을 개별적으로 저장하고 모든 프롬프트에서 다시 만들어야합니다. 예, 더 많은 리소스를 사용하지만 들리는 것처럼 느리지는 않습니다. 기록이 10 만 개가 넘는 경우에만 지연이 눈에 띄기 시작합니다.

핵심 논리는 다음과 같습니다.

# on every Prompt, save new history to dedicated file and recreate full history
# by reading all files, always keeping history from current session on top.
update_history () {
  history -a ${HISTFILE}.$$
  history -c
  history -r
  for f in `ls ${HISTFILE}.[0-9]* | grep -v "${HISTFILE}.$$\$"`; do
    history -r $f
  done
  history -r "${HISTFILE}.$$"
}
export Prompt_COMMAND='update_history'

# merge session history into main history file on bash exit
merge_session_history () {
  cat ${HISTFILE}.$$ >> $HISTFILE
  rm ${HISTFILE}.$$
}
trap merge_session_history EXIT

일부 보호 및 성능 최적화를 포함한 전체 솔루션은 this Gist 를 참조하십시오.

3
Jan Warchoł

사용자 정의 파일에 저장된 무한 히스토리를 선호하기 때문입니다. https://stackoverflow.com/a/19533853/4632019 을 기반으로이 구성을 만듭니다.

export HISTFILESIZE=
export HISTSIZE=
export HISTTIMEFORMAT="[%F %T] "

export HISTFILE=~/.bash_myhistory
Prompt_COMMAND="history -a; history -r; $Prompt_COMMAND"
2
Eugen Konkov

이것은 ZSH에서 작동합니다.

##############################################################################
# History Configuration for ZSH
##############################################################################
HISTSIZE=10000               #How many lines of history to keep in memory
HISTFILE=~/.zsh_history     #Where to save history to disk
SAVEHIST=10000               #Number of history entries to save to disk
#HISTDUP=erase               #Erase duplicates in the history file
setopt    appendhistory     #Append history to the history file (no overwriting)
setopt    sharehistory      #Share history across terminals
setopt    incappendhistory  #Immediately append to the history file, not just when a term is killed
2
Mulki

나는 이것을 오랫동안 원했다. 특히 새 프로젝트에서 다시 실행하기 위해 명령이 실행되는 곳에서 명령을 검색하거나 명령으로 디렉토리를 찾는 기능을 원했다. 따라서 this tool 을 함께 사용하면 전역 CLI 기록을 저장하기위한 이전 솔루션과 percol (C ^ R로 매핑 됨)이라는 대화식 grepping 도구를 결합합니다. 사용하기 시작한 첫 번째 머신에서 여전히 매끄러운 상태입니다. 이제 2 년 이상 된 CLI 내역이 있습니다.

화살표 키에 관한 한 로컬 CLI 기록을 엉망으로 만들지 않지만 전역 기록에 매우 쉽게 액세스 할 수 있습니다 (C ^ R 이외의 다른 것에 매핑 할 수도 있음)

2
Gordon Wells

다음은 내 .bashrc의 스 니펫과 필요한 경우 간단한 설명입니다.

# The following line ensures that history logs screen commands as well
shopt -s histappend

# This line makes the history file to be rewritten and reread at each bash Prompt
PROMPT_COMMAND="$Prompt_COMMAND;history -a; history -n"
# Have lots of history
HISTSIZE=100000         # remember the last 100000 commands
HISTFILESIZE=100000     # start truncating commands after 100000 lines
HISTCONTROL=ignoreboth  # ignoreboth is shorthand for ignorespace and     ignoredups

HISTFILESIZE 및 HISTSIZE는 개인 취향이며 취향에 따라 변경할 수 있습니다.

0
Hopping Bunny