마지막 명령 종료 코드를 bash 프롬프트로 설정

마지막 명령 종료 코드를 bash 프롬프트로 설정

저는 Ubuntu 18.04를 실행 중이고 다음과 같이 bash 프롬프트를 설정하고 싶습니다.

user:~/Documents [14:22:07] 1 $

내 PS1은 다음과 같습니다

ALERT_COLOR="$(tput setaf 1)"

# Display unsuccessful exit codes
function exit_status {
    last_status=$?
    if [[ $last_status != 0 ]]; then
        echo "$ALERT_COLOR[$last_status]"
    fi  
}

parse_git_branch() {
 git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/'
}
if [ "$color_prompt" = yes ]; then
 PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u:\[\033[01;34m\]\w\[\033[01;31m\]$(parse_git_branch)\[\033[00m\] \[\033[36m\][\t] \[$ALERT_COLOR\]$exit_status \[\033[0;37m\]\$ '
else
 PS1='${debian_chroot:+($debian_chroot)}\u:\w$(parse_git_branch)\$ '
fi
unset color_prompt force_color_prompt

종료 코드를 제외하고 모든 것이 잘 작동합니다. 종료 코드가 표시되지 않습니다. $?PS1에서 이 작업을 수행하면 항상 표시됩니다.0

답변1

문제는 여기에 있습니다:

PS1='...\[$ALERT_COLOR\]$exit_status ...\$ '
                        ^^

이는 매개변수 확장이므로 설정한 함수를 호출하지 않습니다. 예를 들어 $(exit_status), from 과 같은 명령 대체에서 함수를 호출해야 합니다 PROMPT_COMMAND. 이렇게 하면 탈출에 주의하세요 \[ .. \]. Bash가 이를 해석합니다.앞으로프롬프트의 다른 확장이므로 프롬프트 문자열에 하드코딩해야 합니다(프롬프트에서 확장된 변수나 기타 항목의 일부가 될 수 없음).

변수를 확장하지 않고 신속하게 탈출하는 것이 당신에게 거꾸로 보인다면, 나는 당신을 비난할 수 없습니다. 하지만이렇게 기록되어 있어요:

또한 다음 표에서는 프롬프트 변수에 나타날 수 있는 특수 문자에 대해 설명합니다 PS1.PS4[...] 문자열을 디코딩한 후, 매개변수 확장 및 명령 대체를 통해 확장,[...]

다음과 같이 작동해야 합니다.

normal_color=$'\033[00m'
red_color=$'\033[41m'
exit_color=$normal_color

set_exit_color() {
    if [ "$?" != 0 ]; then
        exit_color=$red_color
    else
        exit_color=$normal_color
    fi
}

PROMPT_COMMAND=set_exit_color
PS1='\[$exit_color\][$?]\[$normal_color\] \w\$ '

종료 상태를 유지하려면 임시 변수가 필요하다고 생각했지만 분명히 프롬프트에서 확장된 값은 PROMPT_COMMAND수정되지 않습니다 . $?프롬프트 문자열 내부에서 명령 대체를 사용하여 함수를 호출하는 경우 명령 대체에 대한 종료 코드가 적용되므로 해결 방법이 필요합니다. 이 같은:

normal_color=$'\033[00m'
red_color=$'\033[41m'
exit_color=$normal_color

exit_color() {
    exit_code=$?
    if [ "$exit_code" != 0 ]; then
        echo "$red_color"
    else
        echo "$normal_color"
    fi
    return "$exit_code"
}

PS1='\[$(exit_color)\][$?]\[$normal_color\] \w\$ '

명령 대체로 인한 하위 쉘 분기를 저장하기 위해 with 버전을 사용 PROMPT_COMMAND하지만 실제로는 거의 효과가 없습니다.

답변2

나는 3줄의 프롬프트를 갖고 싶기 때문에 다음과 같이 합니다:

۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰ bash ۰۰ 10:56:52
jackman@jackmanVM:~/tmp
+$ cat ~/.bash_prompt
# ... some other stuff ...

__bash_prompt() {
    local last_status=$1
    local cwd=$( sed "s,^$HOME,~," <<<"$PWD" )
    local user_host_path="${debian_chroot:+($debian_chroot) }$(id -un)@$(hostname -s):$cwd"

    # terminal title
    echo -ne "\e]0;$user_host_path\a"

    # separator and date
    local char="۰"
    printf "%s bash %s " "$(jot -s "" -b "$char" $(( $(tput cols) - 18 )) )" "$char$char"
    date '+%T'

    if ((last_status != 0)); then
        local color_bold='\e[0;1m'
        local color_reset='\e[0m'
        printf "$color_bold[%d]$color_reset " $last_status
    fi

    # user@host, directory, git branch
    printf "%s%s\n" "${user_host_path}$(git_current_branch " (%s)")"
}

# ref: https://stackoverflow.com/questions/1039713/different-bash-prompt-for-different-vi-editing-mode
# a single-line PS1 allows the show-mode-in-prompt inputrc setting to be useful
PROMPT_COMMAND='__bash_prompt $?'
PS1='\$ '

~/.bashrc에서 파일을 얻습니다.

종료 상태는 다음과 같이 표시됩니다

۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰ bash ۰۰ 11:05:10
jackman@jackmanVM:~/tmp
+$ sh -c 'exit 42'
۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰ bash ۰۰ 11:05:14
[42] jackman@jackmanVM:~/tmp
+$ false
۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰ bash ۰۰ 11:05:16
[1] jackman@jackmanVM:~/tmp
+$ true
۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰ bash ۰۰ 11:05:17
jackman@jackmanVM:~/tmp
+$ 

함수에서 가장 먼저 하는 일은 다른 명령을 실행하기 전에 마지막 종료 상태를 저장하는 것입니다.

나는 PROMPT_COMMAND를 사용하여 모든 멋진 것들을 출력하고 vi 모드를 사용하고 vi 모드 표시기를 보는 것을 좋아하기 때문에 간단한 PS1만 가지고 있습니다. 나는 또한 이것을 가지고 있습니다 :

۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰۰ bash ۰۰ 10:57:21
jackman@jackmanVM:~/tmp
+$ cat ~/.inputrc
set editing-mode vi

set show-mode-in-prompt on
$if Bash
    # not until bash 4.4, I believe
    # escape sequences: https://stackoverflow.com/a/42107711/7552 
    #set vi-ins-mode-string "+\1\e[5 q\2"
    #set vi-cmd-mode-string ":\1\e[1 q\2"
    set vi-ins-mode-string +
    set vi-cmd-mode-string :
$endif

나는 사용한다로그인 셸로 사용하고 때로는 ksh에 사용하므로 프롬프트 구분 기호에 셸 이름을 넣어 입력 중인 내용을 추적할 수 있습니다.

관련 정보