web-dev-qa-db-fra.com

Invite de commandes avec le dernier code de sortie

Donc, j'ai essayé de personnaliser par invite bash afin qu'il ressemble

[feralin@localhost ~]$ _

avec des couleurs. J'ai réussi à obtenir des couleurs constantes (les mêmes couleurs à chaque fois que je vois l'invite) mais je veux que le nom d'utilisateur ('feralin') apparaisse en rouge au lieu de vert si la dernière commande avait un statut de sortie différent de zéro. Je suis venu avec:

\e[1;33m[$(if [[ $? == 0  ]]; then echo "\e[0;31m"; else echo "\e[0;32m"; fi)\u\e[m@\e[1;34m\h \e[0;35m\W\e[1;33m]$ \e[m

Cependant, d'après mes observations, le $(if ...; fi) semble être évalué une fois, lorsque le .bashrc est exécuté, et le résultat est substitué pour toujours après. Cela rend le nom toujours vert, même si le dernier code de sortie est différent de zéro (comme dans echo $?). Est-ce ce qui se passe? Ou est-ce simplement quelque chose qui ne va pas avec mon invite? Longue question courte, comment puis-je obtenir mon invite à utiliser le dernier code de sortie?

48
feralin

Lorsque vous commencez à vous rapprocher d'une PS1 complexe, vous pouvez envisager d'utiliser Prompt_COMMAND.
Avec cela, vous définissez une fonction et celle-ci sera exécutée après chaque commande pour générer l'invite.

Vous pouvez essayer ce qui suit dans votre ~/.bashrc

Prompt_COMMAND=__Prompt_command # Func to gen PS1 after CMDs

__Prompt_command() {
    local EXIT="$?"             # This needs to be first
    PS1=""

    local RCol='\[\e[0m\]'

    local Red='\[\e[0;31m\]'
    local Gre='\[\e[0;32m\]'
    local BYel='\[\e[1;33m\]'
    local BBlu='\[\e[1;34m\]'
    local Pur='\[\e[0;35m\]'

    if [ $EXIT != 0 ]; then
        PS1+="${Red}\u${RCol}"      # Add red if exit code non 0
    else
        PS1+="${Gre}\u${RCol}"
    fi

    PS1+="${RCol}@${BBlu}\h ${Pur}\W${BYel}$ ${RCol}"
}

Cela devrait faire ce que vous voulez, ce qui vous semble être la ligne que vous voulez ... Regardez un fichier sous-fichier de mon basque si vous voulez voir tout ce que je fais avec ma fonction __Prompt_command.

83
demure

Si vous ne souhaitez pas utiliser la commande Prompt, vous devez prendre en compte deux éléments:

  1. obtenir la valeur de $? avant toute chose, sinon ça va être écrasé
  2. échapper à tous les $ de la PS1 (donc, cela n’est pas évalué lorsque vous l’affectez)

Exemple de travail utilisant une variable

PS1="\$(VALU="\$?" ; echo \$VALU ; date ; if [ \$VALU == 0 ]; then echo zero; else echo nonzero; fi) " 

Exemple de travail sans variable

Ici, le si doit être la première chose à faire, avant toute commande qui écraserait le $?.

PS1="\$(if [ \$? == 0 ]; then echo zero; else echo nonzero; fi) "

Remarquez comment \$() est échappé afin de ne pas l'exécuter immédiatement, mais chaque fois que vous utilisez PS1. Aussi toutes les utilisations de \$?

11
helios

Je voulais conserver les couleurs par défaut de Debian, imprimer le code exact et ne l'imprimer qu'en cas d'échec:

# Show exit status on failure.
Prompt_COMMAND=__Prompt_command

__Prompt_command() {
    local curr_exit="$?"

    local BRed='\[\e[0;91m\]'
    local RCol='\[\e[0m\]'

    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '

    if [ "$curr_exit" != 0 ]; then
        PS1="[${BRed}$curr_exit${RCol}]$PS1"
    fi
}
3
Velkan

@Demure amélioré

Je pense que cela est important car le statut de sortie n’est pas toujours 0 ou 1.

if [ $EXIT != 0 ]; then
    PS1+="${Red}${EXIT}:\u${RCol}"      # Add red if exit code != 0
else
    PS1+="${Gre}${EXIT}:\u${RCol}"      # Also displays exit status
fi
0
user1340624