bash_history에 실패한 bash 명령을 작성하는 것을 방지하는 방법

bash_history에 실패한 bash 명령을 작성하는 것을 방지하는 방법

어디서도 본 적 없는 미묘한 역사적 행태를 찾아봅니다.

  1. 터미널 세션 중에 종료 상태에 관계없이 모든 명령이 메모리 기록에 추가되기를 원합니다.
  2. 세션을 종료한 후 메모리 내 기록이 디스크에 기록되는 동안 ~/.bash_history실패한 명령을 무시하고 싶습니다 .

추론이 명확하기를 바랍니다. 세션 내 기록의 가장 일반적인 용도 중 하나는 사소한 편집을 통해 또는 일부 환경 사실을 변경한 후 더 나은 결과를 얻기 위해 마지막(실패한) 명령을 다시 시도하는 것입니다.

그러나 동시에 나는 나의 오랜 역사가 나쁜 질서로 뒤덮이는 것을 원하지 않습니다.

나는 보았다이 게시물, (1) 마지막 명령의 종료 상태를 확인하는 방법, (2) 인덱스별로 기록 항목을 삭제하는 방법을 보여줍니다.

그리고 난 봤어이 답변trap, 세션이 끝날 때 명령을 실행하는 방법을 보여줍니다 .

(저도 공부했어요.이것은 슈퍼 답변입니다, 이는 역사적 조작과 관련된 많은 단점을 다루는 것으로 보입니다. 그것이 얼마나 관련성이 있는지는 잘 모르겠지만. )

목표를 달성하는 방법에 대한 대략적인 아이디어는 있지만 bash 프로그래밍에 대한 경험이 많지 않아 구현하는 데 어려움을 겪고 있습니다. 내 계획:

  • $TEMP/.bash_history_failures_IDENTIFIERIDENTIFIER여러 세션이 서로 간섭하지 않도록 보장하기 위해 각 터미널 세션에 대해 새 파일을 만들고 일부 세션별 값(PID?)으로 대체합니다.
  • number=$(history 1)및 의 조합을 사용하여 [ $exit_status -eq 127 ]각 오류 명령의 색인을 현재 세션의 실패 파일에 기록합니다.
  • 종료 시 코드를 실행하기 위해 후크를 사용하여 trap이 세션에서 실패한 파일의 인덱스를 반복하는 함수를 호출하여 history -d $number각 항목에 대해 작업을 수행합니다.
  • ~/.bash_historyHISTCONTROL마지막으로 내 설정에 따라 나머지 메모리 내 기록(성공적인 명령만 기록되어야 함)을 기록하도록 했습니다.

내 제안이 효과가 있을까요? 내가 무엇을 간과하고 있습니까? 기록에서 항목을 오름차순으로 삭제하는 데 문제가 있습니까? 세션별로 고유한 파일을 생성하는 훌륭하고 안정적인 방법은 무엇입니까?


"실패한" 명령이란 무엇입니까?

장기 기록에 사용자 오류가 포함되는 것을 원하지 않습니다.

  • 명령이 존재하지 않습니다
  • 문법 오류

다른 이유로 인해 명령을 실행할 수 없는 경우에도(예: 권한 부족, 입력 경로 없음) 명령을 올바르게 유지하고 싶습니다.

마음에 떠오르는 두 가지 예는 다음과 같이 코드 한 줄에 세미콜론을 삽입하는 것을 자주 잊어버리는 경우입니다.

for pkg in $(ls ./packages); do cp ./.eslintrc.yml ./packages/$pkg/; done

나는 준결승전을 잘못된 위치에 놓은 항목이 역사에 포함되는 것을 원하지 않습니다.

반면에 올바른 옵션을 찾으려면 일반적으로 여러 번 시도해야 하며 cut대부분의 오류는 인수를 지정할 때 구문 오류입니다.

내 긴 bash 기록이 제대로 작동하는 명령을 얻으려는 수많은 실패한 시도를 간과할 수 있다면 기쁠 것입니다. 예를 들어 우연히 결과가 없는 검색이 포함된 기록에는 관심이 없습니다.


다음을 추가하도록 편집되었습니다.

이것하스트셸 구성 파일에 항목을 추가하는 것과 같은 기록 관리를 위한 CLI 도구는 다음과 같습니다.

$ hstr --show-configuration

# HSTR configuration - add this to ~/.bashrc
alias hh=hstr                    # hh to be alias for hstr
export HSTR_CONFIG=hicolor       # get more colors
shopt -s histappend              # append new history items to .bash_history
export HISTCONTROL=ignorespace   # leading space hides commands from history
export HISTFILESIZE=10000        # increase history file size (default is 500)
export HISTSIZE=${HISTFILESIZE}  # increase history size (default is 500)
# ensure synchronization between bash memory and history file
export PROMPT_COMMAND="history -a; history -n; ${PROMPT_COMMAND}"
# if this is interactive shell, then bind hstr to Ctrl-r (for Vi mode check doc)
if [[ $- =~ .*i.* ]]; then bind '"\C-r": "\C-a hstr -- \C-j"'; fi
# if this is interactive shell, then bind 'kill last command' to Ctrl-x k
if [[ $- =~ .*i.* ]]; then bind '"\C-xk": "\C-a hstr -k \C-j"'; fi

hstr의 코드 기반에서 솔루션을 잠식할 수 있다는 예감이 듭니다.

답변1

이 시도:

export PROMPT_COMMAND='LAST_COMMAND_EXIT=$? && history -a && test 127 -eq $LAST_COMMAND_EXIT && head -n -2 $HISTFILE >${HISTFILE}_temp && mv ${HISTFILE}_temp $HISTFILE'

종료 상태가 127인 경우 histfile의 마지막 두 줄(타임스탬프 및 명령)을 삭제하면 됩니다. 나에게는 잘 작동합니다. 기록에 타임스탬프가 없으면 사용해야 합니다 head -n -1.-2

물론 이 줄을 .bashrc에 추가하여 이를 지속되게 만들어야 합니다.

답변2

Bash 구성 파일에 다음을 추가하세요.

nohist() { history -d $HISTCMD; }; trap nohist ERR

편집: 오류 줄을 쉽게 검색할 수 있기 때문에 더 좋습니다.

ce() { eval "$BASH_COMMAND;  e='$BASH_COMMAND'"; false; }
if [[ $- == *i* ]]; then trap ce ERR; fi # capture error command
alias e='$e' # type e and then expand with ctrl-alt-e

또한 재사용을 위해 모든 출력을 캡처합니다(그러나 에코 및 히스트에 문제가 있습니다).

save_output() { 
   exec 1>&3 
   { [ -f /tmp/current ] && mv /tmp/current /tmp/last; }
   exec > >(tee /tmp/current)
}

exec 3>&1
trap save_output DEBUG

https://stackoverflow.com/a/48398357/4240654

관련 정보