BASH 기록에 성공한 명령만 유지

BASH 기록에 성공한 명령만 유지

때때로 나는 명령의 구문을 오해합니다.

# mysql -d test
mysql: unknown option '-d'
# echo $?
2

나는 다시 시도하고 올바르게 이해합니다.

# mysql --database test
Welcome to the MySQL monitor.
mysql >
...

오류 코드가 0이 아닌 첫 번째 명령이 기록에 들어가지 않도록 하려면 어떻게 해야 합니까?

답변1

나는 당신이 그것을 정말로 원하지 않는다고 생각합니다. 내 일반적인 작업 흐름은 다음과 같습니다.

  • 명령을 입력하세요
  • 실행해 보세요
  • 실패했음을 확인하세요.
  • UP 키를 누르세요
  • 명령 편집
  • 다시 실행하세요

이제 실패한 명령이 기록에 저장되지 않으면 쉽게 수정하고 다시 실행할 수 없습니다.

답변2

내가 생각할 수 있는 유일한 방법은 history -d에서 사용하는 것입니다 $PROMPT_COMMAND. 이 접근 방식이나 다른 접근 방식의 문제점은 명령이 오류와 함께 종료되었는지 또는 0이 아닌 종료 코드로 성공적으로 완료되었는지 알 수 없다는 것입니다.

$ grep non_existent_string from_file_that_exists
$ echo $?
1

답변3

마지막으로 잘못된 댓글을 남겨서 수정하는 것이 좋지만, 그 이후에는 곧 혼란을 야기할 수 있는 쓰레기가 됩니다.

내 접근 방식은 2단계입니다. 실패한 명령을 저장하고 나중에 제거하는 것입니다.

다음과 같은 경우 실패하는 명령을 저장합니다.

error_handler() {
    FAILED_COMMANDS="$(history | tail -1l | cut -c -5) $FAILED_COMMANDS"
}

trap error_handler ERR

trap command signalscommand중 하나가 "발생"하면 실행됩니다 signals.

$(command), 을 실행 command하고 해당 출력을 캡처합니다.

명령이 실패하면 이 코드 조각은 기록 번호를 캡처합니다.기록에 저장된 마지막 명령, 향후 삭제를 위해 변수에 저장합니다.

간단하지만 다음과 함께 제대로 작동하지 않습니다 HISTCONTROL. HISTIGNORE– 변수 중 하나로 인해 명령이 기록에 저장되지 않은 경우,기록에 저장된 마지막 명령의 기록 번호이전 명령의 명령입니다. 따라서 잘못된 명령이 기록에 저장되지 않으면 이전 명령이 삭제됩니다.

이 경우에는 올바르게 작동하는 약간 더 복잡한 버전입니다.

debug_handler() {
    LAST_COMMAND=$BASH_COMMAND;
}

error_handler() {
    local LAST_HISTORY_ENTRY=$(history | tail -1l)

    # if last command is in history (HISTCONTROL, HISTIGNORE)...
    if [ "$LAST_COMMAND" == "$(cut -d ' ' -f 2- <<< $LAST_HISTORY_ENTRY)" ]
    then
        # ...prepend it's history number into FAILED_COMMANDS,
        # marking the command for deletion.
        FAILED_COMMANDS="$(cut -d ' ' -f 1 <<< $LAST_HISTORY_ENTRY) $FAILED_COMMANDS"
    fi
}

trap error_handler ERR
trap debug_handler DEBUG

나중에 저장된 명령을 제거하십시오.

exit_handler() {
    for i in $(echo $FAILED_COMMANDS | tr ' ' '\n' | uniq)
    do
        history -d $i
    done
    FAILED_COMMANDS=
}

trap exit_handler EXIT

설명:

Bash를 종료할 때 각 고유 기록 번호에 대해 해당 기록 항목을 제거한 다음 이미 삭제된 명령에서 기록 번호를 상속받은 명령을 제거하지 않도록
선택을 취소합니다 .FAILED_COMMANDS

FAILED_COMMANDS중복이 없다고 확신한다면 간단하게 반복할 수 있습니다
(예: write for i in $FAILED_COMMANDS). 그러나 가장 큰 것부터 가장 작은 것까지 정렬되지 않을 것으로 예상되는 경우(이 경우 항상 정렬됨)를 uniq로 바꾸십시오 sort -rnu.

기록 번호는 FAILED_COMMANDS고유해야 하며 항목을 삭제하면 다음 명령 번호가 이동되기 때문에 가장 큰 것에서 가장 작은 것까지 정렬되어야 합니다. 를 발행하면 history -d 23번째 항목이 2번째 항목이 되고, 4번째 항목이 3번째 항목이 됩니다.

그렇기 때문에 이 코드를 사용할 때 저장된 가장 큰 숫자보다 작거나 같은 history -d <n>
곳을nFAILED_COMMANDS
수동으로 호출할 수 없으며 코드가 제대로 작동할 것으로 기대할 수 없습니다.

exit_handler에 연결하는 것이 아마도 좋은 생각일 것입니다 EXIT. 하지만 언제든지 더 일찍 호출할 수도 있습니다.

관련 정보