L'invite du terminal ne se termine pas correctement


172

J'ai un problème où si je tape de très longues commandes dans bash, le terminal ne rendra pas ce que je tape correctement. Je m'attendrais à cela si j'avais une commande comme celle-ci:

username@someserver ~/somepath $ ssh -i /path/to/private/key
myusername@something.someserver.com

La commande doit être rendue sur deux lignes. Au lieu de cela, il se déroulera souvent et commencera à écrire par-dessus mon invite, un peu comme ceci:

myreallylongusername@something.somelongserver.comh -i /path/to/private/key

Si je décide de revenir en arrière et de changer d'argument, rien ne dit où le curseur apparaîtra, parfois au milieu de l'invite, mais généralement sur la ligne ci-dessus où je tape.

L'amusement supplémentaire se produit quand quand je Upà une commande précédente. J'ai essayé cela à la fois dans gnome-terminal et terminator, ainsi que sur i3 et Cinnamon. Quelqu'un a suggéré que c'était ma réponse, alors voici:

\[\033[01;32m\]\u:\[\033[01;34m\] \W\033[01;34m \$\[\033[00m\]

Ctrll, resetet cleartous font ce qu’ils disent, mais c’est quand je tape la commande ou que Uples mêmes choses se passent.

J'ai vérifié et checkwinsizeest activé dans bash. Cela se produit sur 80x24 et d'autres tailles de fenêtre.

Est-ce juste quelque chose que j'apprends à vivre? Y a-t-il un morceau de magie que je devrais savoir? Je me suis contenté d'utiliser une invite très courte, mais cela ne résout pas le problème.


1
Donc, utiliser la commande le env -i bash --norccorrige. Les correspondances $ COLUMNS et $ LINES. Est-ce que cela signifie qu'il y a quelque chose de drôle avec mon .bashrc?
Muricula

J'ai donc commenté mon .bashrc et j'ai fini par isoler mon invite en tant que partie problématique, en particulier la syntaxe de coloration impliquée. Quel est le problème avec la PS1 ci-dessus?
Muricula

1
\[\033[01;32m\]\u: \[\033[01;34m\]\W \[\033[01;34m\] \$ \[\033[0m\]semble éviter le comportement bizarre - mais je ne sais pas si cela respecte complètement votre invite d'origine ...

1
Selon cette réponse sur serverfault , utiliseztput smam
Samveen

Réponses:


189

Les séquences non imprimables doivent être incluses dans \[et\] . En regardant votre PS1, il y a une séquence non fermée après \W. Mais la deuxième entrée est redondante et répète la déclaration précédente "1; 34" .

\[\033[01;32m\]\u:\[\033[01;34m\] \W\033[01;34m \$\[\033[00m\]
                  |_____________|               |_|
                         |                       |
                         +--- Let this apply to this as well.

En tant que tel, il aurait dû être prévu de colorer:

\[\033[1;32m\]\u:\[\033[1;34m\] \W \$\[\033[0m\]
                               |_____|
                                  |
                                  +---- Bold blue.

Conserver "l'original" devrait également fonctionner:

\[\033[1;32m\]\u:\[\033[1;34m\] \W\[\033[1;34m\] \$\[\033[0m\]
                                  |_|         |_|
                                   |           |
                                   +-----------+-- Enclose in \[ \]

Modifier:

La raison du comportement est parce que bashcroit que l'invite est plus longue qu'elle ne l'est réellement. Comme exemple simple, si on utilise:

PS1="\033[0;34m$"
       1 2345678

L'invite est censée être composée de 8 caractères et non de 1. En tant que telle, si la fenêtre du terminal comporte 20 colonnes, après avoir tapé 12 caractères, il est supposé être composé de 20 caractères. Ceci est également évident si on essaie ensuite de faire un retour arrière ou Ctrl+u. Il s’arrête à la colonne 9.

Toutefois, la nouvelle ligne ne commence pas non plus, à moins qu’une des colonnes ne figure dans la dernière colonne. La première ligne est par conséquent remplacée.

Si vous continuez à taper, la ligne doit passer à la ligne suivante après 32 caractères.


Si vous avez - ou si quelqu'un - a une explication sur ce qui dans la séquence d'origine a exactement fait répéter la ligne sur elle-même, je serais intéressé de le savoir. Également +1 pour la façon dont vous avez montré cela visuellement.

1
@ illuminÉ: Je n'ai pas regardé la source, mais ajouté une mise à jour avec une note sur le comportement d'observation.
Runium

En cas de problème, vous pouvez utiliser ce site web pour en créer un nouveau - bashrcgenerator.com
divinedragon 11/12

C'est incroyable, merci @Runium - cela vous dérangerait-il de dire comment vous avez su cela? J'aimerais trouver de la documentation à ce sujet.
Nycynik

2
@nycynik: Observation. Je suppose que le plus proche de la documentation à ce sujet est le code source ...
Runium

84

La plupart du temps, la taille de la fenêtre supposée par le terminal n’est pas la même que la taille réelle de votre fenêtre. Si vous utilisez bash, vous pouvez essayer ceci.

$ shopt checkwinsize

Si vous n'obtenez pas

checkwinsize    on

Puis activez-le avec

$ shopt -s checkwinsize

Ensuite, essayez simplement d’exécuter une autre commande (comme ls) ou de redimensionner la fenêtre une fois, ce qui précède fonctionne pour moi à chaque fois.

Pour les systèmes Redhat en particulier, le problème est souvent causé par une mauvaise configuration ~/.bashrcpour ne pas appeler /etc/bashrc. Normalement, bash charge ~/.bashrcce qui est appelé /etc/bashrc, ce qui contient par défaut shopt -s checkwinsize.


Même problème avec OS X. Apparemment, si vous appelez "login" pour démarrer votre terminal, il démarre bash de manière à lire / etc / bashrc, mais si vous appelez directement bash, le fichier ~ / .bashrc ne fonctionne pas. source des choses par défaut afin que vous obteniez l'effet d'emballage étrange. Merci!
rogerdpack

Cela a fonctionné pour moi aussi. Les couleurs ne sont pas allumées sur ce serveur, les appels ont été corrects /etc/bashrc, tout le reste était bon à faire ... s’avère que c’est la cause des problèmes d’emballage.
Dhaupin


1
On dirait une bonne solution. Mais cela ne fonctionne pas dans ma session SSH, cependant. Pas certain de pourquoi. J'ai exécuté la commande shopt -s checkwinsizedans la session SSH. Mais l'emballage persiste.
Qiang Xu

C’était précisément mon problème: un utilisateur .bashrc n’appelait pas / etc / bashrc, ce qui causait des dégâts.
Sobrique

9

Comme mentionné dans d'autres réponses, les séquences non imprimables telles que celles qui \e[0;30mdoivent être enveloppées \[...\].

De plus (et ce que je ne vois pas encore mentionné), il semble que cela \r\ndevrait être en dehors du \[...\]si vous avez une invite multiligne. Il m'a fallu des essais et des erreurs pour finalement comprendre cela.


8

Une fois, j’ai lu quelque part (je ne sais plus où) que l’utilisation \001et la \002place de \[et \]peuvent résoudre ce problème. Ça l'a fait pour moi.

En passant, définir PS1 n'a pas à paraître laid.

green="\001$(tput setaf 2)\002"
blue="\001$(tput setaf 4)\002"
dim="\001$(tput dim)\002"
reset="\001$(tput sgr0)\002"

PS1="$dim[\t] " # [hh:mm:ss]
PS1+="$green\u@\h" # user@host
PS1+="$blue\w\$$reset " # workingdir$

export PS1
unset green blue dim reset

2
Ma PS1 appelle une commande qui imprime des séquences d'échappement à l'origine du problème de l'OP. Seule cette solution résout le problème pour moi.
RickMeasham

7

Cela ressemble à un problème avec vos paramètres de variable COLUMNS& LINESenvironment. Lorsque vous redimensionnez la fenêtre, elles sont généralement définies automatiquement par gnome-terminal (je crois), vous pouvez les forcer à être définies manuellement en lançant la commande resize.

Exemple

Si je redimensionne mon gnome-terminal à 79x17, mes variables apparaissent comme suit:

$ echo $COLUMNS; echo $LINES
79
17

Je peux le forcer comme ça:

$ resize
COLUMNS=79;
LINES=17;
export COLUMNS LINES;

1
Intéressant, mais n'aide pas.
Muricula

1
Cela corrigeait mon problème: les lignes n'étaient pas correctement enveloppées après l'exécution de la commande "screen". Merci!!
nukeguy

5

Pour éviter le retour à la ligne, vous pouvez également augmenter le nombre de colonnes en utilisant, par exemple:

stty columns 120

1
Ce n'est pas une très bonne idée, il a foiré brutalement vim
phil294

3

Le même problème peut également être provoqué par l'utilisation de symboles unicode larges (comme à partir de https://stackoverflow.com/a/34812608/1657819 ). Voici l'extrait cause du problème ( l' esprit le $Greenet $Redsont correctement échappé des chaînes de couleurs):

FancyX='\342\234\227'
Checkmark='\342\234\223'


# Add a bright white exit status for the last command
PS1="$White\$? "
# If it was successful, print a green check mark. Otherwise, print
# a red X.
if [[ $Last_Command == 0 ]]; then
    PS1+="$Green$Checkmark "
else
    PS1+="$Red$FancyX "
fi

Bash ne peut pas calculer la longueur correctement, aussi pourrait-il être plus simple d’échapper deux des trois parties de ces symboles larges.

FancyX='\[\342\234\]\227'
Checkmark='\[\342\234\]\223'

Logique. Ce que je suppose, c'est que bash compte les personnages. Parce que le X prend un caractère mais est écrit en tant que 3, il faut en inclure 2 pour corriger le comptage. @blauhirn answer explique également comment utiliser une fonction avec \001et \002.
akostadinov

Pour votre information, voici comment trouver des caractères Unicode multi-octets dans ce format: stackoverflow.com/a/602924/520567
akostadinov
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.