Also habe ich versucht, per Bash-Eingabeaufforderung so anzupassen, dass es so aussieht
[feralin@localhost ~]$ _
mit Farben. Ich habe es geschafft, konstante Farben zu erhalten (jedes Mal, wenn ich die Eingabeaufforderung sehe, die gleichen Farben), aber ich möchte, dass der Benutzername ('feralin') rot statt grün angezeigt wird, wenn der letzte Befehl einen Exit-Status ungleich Null hatte. Ich hatte die Idee dass:
\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
Nach meinen Beobachtungen $(if ...; fi)
scheint das jedoch einmal ausgewertet zu werden, wenn das ausgeführt .bashrc
wird, und das Ergebnis wird für immer danach ersetzt. Dadurch wird der Name immer grün, auch wenn der letzte Beendigungscode ungleich Null ist (wie in, echo $?
). Passiert das? Oder stimmt einfach etwas anderes mit meiner Eingabeaufforderung nicht? Lange Frage kurz, wie bekomme ich meine Aufforderung, den letzten Exit-Code zu verwenden?
.bashrc
wird" - das bedeutet, dass Sie beim Zuweisen die falschen Anführungszeichen setzenPS1
. Muss einfach sein, nicht doppelt. Wenn dies nicht hilft, werden Sie$?
von etwas anderem zurückgesetzt, das ausgeführt wird, bevor Ihre Eingabeaufforderung gedruckt wird.set -x
ermöglicht das Aufspüren solcher Befehle.Antworten:
Wenn Sie anfangen, an eine komplexe PS1 zu grenzen, sollten Sie die Verwendung in Betracht ziehen
PROMPT_COMMAND
.Damit setzen Sie es auf eine Funktion und es wird nach jedem Befehl ausgeführt, um die Eingabeaufforderung zu generieren.
Sie könnten Folgendes in Ihrem versuchen
~/.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}" }
Dies sollte tun, was es klingt Linie, die Sie wollen. Schauen Sie sich die Subdatei von my bashrc an , wenn Sie alle Dinge sehen möchten, die ich mit meiner
__prompt_command
Funktion mache .quelle
EXIT
als Vorwärtskompatibilitätspraxis zu verwenden. Siehe pubs.opengroup.org/onlinepubs/009695399/basedefs/… , vierter Absatz - Der Namespace von All-Caps-Namen wird für Variablen verwendet, die für das System oder die Shell von Bedeutung sind. Das Festhalten an Kleinbuchstaben verhindert das Überschreiben einer Umgebungsvariablen oder einer in die Shell integrierten Variablen, wenn nur versucht wird, eine Shell-Variable zuzuweisen. Zugegeben, mit einer lokalen Erklärung, dass das Überschreiben nur vorübergehend ist, was es hier weniger problematisch als gewöhnlich macht, aber immer noch nicht ideal.PROMPT_COMMAND="__prompt_command; ${PROMPT_COMMAND}"
das Öffnen eines neuen Tabs / Fensters im aktuellen Arbeitsverzeichnis aktivieren, das weiterhin funktioniert.PROMPT_COMMAND=update_terminal_cwd
Standardmäßig wird der CWD protokolliert.PIPESTATUS
bietet weitere Informationen zum zuletzt ausgeführten Befehl oder zur zuletzt ausgeführten Pipe.${PIPESTATUS[@]}
wird eine Folge von Nullen sein, wie0 0 0
für den Fall, dass alle Befehle korrekt ausgeführt wurden, andernfalls hat es keine Nullen wie0 127 1
. Man kann mit auf Erfolg prüfenif $(echo ${PIPESTATUS[@]} | grep -qEe '^0( 0)*$'); then echo "good"; else echo "bad"; fi
.Wenn Sie den Eingabeaufforderungsbefehl nicht verwenden möchten, müssen Sie zwei Dinge berücksichtigen:
Arbeitsbeispiel mit einer Variablen
PS1="\$(VALU="\$?" ; echo \$VALU ; date ; if [ \$VALU == 0 ]; then echo zero; else echo nonzero; fi) "
Arbeitsbeispiel ohne Variable
Hier muss das if das erste sein, bevor ein Befehl das überschreibt
$?
.PS1="\$(if [ \$? == 0 ]; then echo zero; else echo nonzero; fi) "
Beachten Sie, wie das
\$()
maskiert wird, damit es nicht sofort ausgeführt wird, sondern jedes Mal, wenn PS1 verwendet wird. Auch alle Verwendungen von\$?
quelle
export PS1="\$([ \$? == 0 ] && echo ✅ || echo ⚠️ ) \h:\W \u\n\$ "
virtualenv
diePS1
bei Aktivierung Variablen Variablen voranstellen . VerwendenPROMPT_COMMAND
würde nicht funktionieren!\${PIPESTATUS[-1]}
, können Sie den Exit-Status des letzten Befehls abrufen, auch wenn dies nicht das erste in Ihrem Befehl istPS1
.Ich wollte die Standardfarben von Debian beibehalten, den genauen Code drucken und ihn nur bei einem Fehler drucken:
# 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 }
quelle
Kompakte Lösung:
PS1='... $(code=${?##0};echo ${code:+[error: ${code}]})'
Dieser Ansatz erfordert nicht
PROMPT_COMMAND
(anscheinend kann dies manchmal langsamer sein) und wird gedruckt,[error: <code>]
wenn der Exit-Code nicht Null ist, und nichts, wenn er Null ist:... > false ... [error: 1]> true ... >
Ändern Sie das
[error: ${code}]
Teil nach Ihren Wünschen,${code}
wobei der zu druckende Code ungleich Null ist.Beachten Sie die Verwendung von,
'
um sicherzustellen, dass die Inline-$()
Shell ausgeführt wird, wenn PS1 später ausgewertet wird, und nicht, wenn die Shell gestartet wird.Als Bonus können Sie es in Rot bunt machen, indem Sie es
\e[01;31m
vor und\e[00m
nach dem Zurücksetzen hinzufügen :PS1='... \e[01;31m$(code=${?##0};echo ${code:+[error: ${code}]})\e[00m'
- -
Wie es funktioniert:
${?##0}
liest der den Exit-Code$?
des vorherigen Befehls##
wird jedes0
Muster von Anfang an entfernen und ein0
Ergebnis effektiv zu einer leeren Variable machen (danke @blaskovicz für den Trick).code
Variablen zu, da wir eine weitere Ersetzung vornehmen müssen, und sie können nicht verschachtelt werden${code:+REPLACEMENT}
druckt dasREPLACEMENT
Teil nur, wenn die Variablecode
gesetzt ist (nicht leer).[error: ${code}]
quelle
@Demure verbessert
Ich denke, das ist wichtig, weil es nicht immer den Exit-Status 0 oder 1 gibt.
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
quelle
IFS=0
, wird diesif [ != 0 ]
bei der Erweiterung (natürlich mit einem Null-Exit-Code). Wenn Sieif [ "$EXIT" != 0 ]
es machen, wird das vermieden.Um das ursprüngliche Eingabeaufforderungsformat (nicht nur Farben) beizubehalten, können Sie Folgendes an das Ende von anhängen
~/.bashrc
:PS1_ORIG=$PS1 # original primary prompt value PROMPT_COMMAND=__update_prompt # Func to be re-evaluated after each command is executed __update_prompt() { local PREVIOUS_EXIT_CODE="$?" if [ $PREVIOUS_EXIT_CODE != 0 ]; then local RedCol='\[\e[0;31m\]' local ResetCol='\[\e[0m\]' local replacement="${RedCol}\u${ResetCol}" # Replace username color PS1=${PS1_ORIG//]\\u/]$replacement} ## Alternative: keep same colors, append exit code #PS1="$PS1_ORIG[${RedCol}error=$PREVIOUS_EXIT_CODE${ResetCol}]$ " else PS1=$PS1_ORIG fi }
Siehe auch den Kommentar zum alternativen Ansatz, bei dem die Farbe des Benutzernamens beibehalten und nur der Fehlercode in Rot an das Ende des ursprünglichen Eingabeaufforderungsformats angehängt wird
quelle
Warum habe ich selbst nicht darüber nachgedacht?) Ich fand das sehr interessant und fügte diese Funktion meinem ' Info-Bar' -Projekt hinzu. Die Augen werden rot, wenn der letzte Befehl fehlgeschlagen ist.
#!/bin/bash eyes=(O o ∘ ◦ ⍤ ⍥) en=${#eyes[@]} mouth='_' face () { # gen random face [[ $error -gt 0 ]] && ecolor=$RED || ecolor=$YLW if [[ $1 ]]; then printf "${eyes[$[RANDOM%en]]}$mouth${eyes[$[RANDOM%en]]}" else printf "$ecolor${eyes[$[RANDOM%en]]}$YLW$mouth$ecolor${eyes[$[RANDOM%en]]}$DEF" fi } info () { error=$? [[ -d .git ]] && { # If in git project folder add git status to info bar output git_clr=('GIT' $(git -c color.ui=always status -sb)) # Colored output 4 info git_tst=('GIT' $(git status -sb)) # Simple output 4 test } printf -v line "%${COLUMNS}s" # Set border length date=$(printf "%(%a %d %b %T)T") # Date & time 4 test test=" O_o $PWD ${git_tst[*]} $date o_O " # Test string step=$[$COLUMNS-${#test}]; [[ $step -lt 0 ]] && step=0 # Count spaces line="$GRN${line// /-}$DEF\n" # Create lines home="$BLD$BLU$PWD$DEF" # Home dir info date="$DIM$date$DEF" # Colored date & time #------+-----+-------+--------+-------------+-----+-------+--------+ # Line | O_o |homedir| Spaces | Git status | Date| o_O | Line | #------+-----+-------+--------+-------------+-----+-------+--------+ printf "$line $(face) $home %${step}s ${git_clr[*]} $date $(face) \n$line" # Final info string } PS1='${debian_chroot:+($debian_chroot)}\n$(info)\n$ ' case "$TERM" in xterm*|rxvt*) PS1="\[\e]0;${debian_chroot:+($debian_chroot)} $(face 1) \w\a\]$PS1";; esac
quelle