Dấu nhắc thiết bị đầu cuối không gói chính xác


171

Tôi có một vấn đề là nếu tôi gõ các lệnh rất dài trong bash thì thiết bị đầu cuối sẽ không hiển thị những gì tôi đang gõ chính xác. Tôi hy vọng rằng nếu tôi có một lệnh như sau:

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

Lệnh sẽ hiển thị trên hai dòng. Thay vào đó, nó sẽ thường quấn quanh và bắt đầu viết lên đầu lời nhắc của tôi, hơi giống như thế này:

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

Nếu tôi quyết định quay lại và thay đổi một số đối số thì sẽ không biết con trỏ sẽ hiển thị ở đâu, đôi khi ở giữa dấu nhắc, nhưng thường ở dòng phía trên nơi tôi đang gõ.

Thêm niềm vui xảy ra khi tôi Upđến một lệnh trước đó. Tôi đã thử điều này trong cả gnome-terminal và terminator và trên i3 và Cinnamon. Ai đó đề nghị đó là lời nhắc của tôi, vì vậy đây là:

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

Ctrll, resetcleartất cả làm những gì họ nói, nhưng khi tôi gõ lệnh trở lại hoặc Upđiều tương tự xảy ra.

Tôi đã kiểm tra và checkwinsizeđược kích hoạt trong bash. Điều này xảy ra trên 80x24 và các kích thước cửa sổ khác.

Đây có phải là thứ tôi học được để sống cùng không? Có một số phép thuật mà tôi nên biết? Tôi đã giải quyết chỉ bằng cách sử dụng một dấu nhắc thực sự ngắn, nhưng điều đó không khắc phục được vấn đề.


1
Vì vậy, bằng cách sử dụng lệnh env -i bash --norcsửa nó. Trận đấu $ COLUMNS và $ LINES. Điều đó có nghĩa là có gì đó buồn cười với .bashrc của tôi phải không?
Muricula

Vì vậy, tôi đã nhận xét .bashrc của mình và cố gắng cô lập dấu nhắc của tôi là phần có vấn đề, cụ thể là cú pháp tô màu có liên quan. Có gì sai với PS1 ở trên?
Muricula

1
\[\033[01;32m\]\u: \[\033[01;34m\]\W \[\033[01;34m\] \$ \[\033[0m\]dường như tránh sự kỳ lạ trong hành vi - nhưng không biết liệu nó có tôn trọng hoàn toàn lời nhắc ban đầu của bạn không ...

1
Theo câu trả lời này trên serverfault , hãy sử dụngtput smam
Samveen

Câu trả lời:


189

Trình tự không in được nên được đính kèm trong \[\] . Nhìn vào PS1 của bạn, nó có một chuỗi không bị khóa sau \W. Nhưng, mục thứ hai là dư thừa cũng như nó lặp lại tuyên bố trước đó "1; 34" .

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

Vì vậy, điều này nên có ý định tô màu:

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

Giữ "bản gốc" này cũng sẽ hoạt động:

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

Biên tập:

Lý do cho hành vi này là bởi vì bashtin rằng dấu nhắc đó dài hơn thực tế. Ví dụ đơn giản, nếu một người sử dụng:

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

Lời nhắc được cho là 8 ký tự chứ không phải 1. Như vậy, nếu cửa sổ đầu cuối là 20 cột, sau khi nhập 12 ký tự, nó được cho là 20 ký tự và bao quanh. Điều này cũng rõ ràng nếu một sau đó cố gắng làm backspace hoặc Ctrl+u. Nó dừng lại ở cột 9.

Tuy nhiên, nó cũng không bắt đầu dòng mới trừ khi một dòng nằm trên cột cuối cùng, kết quả là dòng đầu tiên bị ghi đè.

Nếu một người tiếp tục gõ dòng nên quấn đến dòng tiếp theo sau 32 ký tự.


Nếu bạn có - hoặc bất cứ ai - có một lời giải thích về chính xác những gì trong chuỗi ban đầu khiến dòng lặp lại trên chính nó, tôi sẽ quan tâm đến việc biết điều đó. Cũng +1 cho cách bạn thể hiện điều này một cách trực quan.

1
@ illuminÉ: Không nhìn vào nguồn, nhưng đã thêm một bản cập nhật kèm theo ghi chú về hành vi từ quan sát.
Runium

Chỉ trong trường hợp bạn gặp phải bất kỳ vấn đề nào, bạn có thể sử dụng trang web này để tạo một trang web mới - bashrcgenerator.com
divinedragon

Điều này thật tuyệt vời, cảm ơn bạn @Runium - bạn có phiền khi chia sẻ làm thế nào bạn biết điều này? Tôi rất thích tìm một số tài liệu về điều này.
nycynik

2
@nycynik: Quan sát. Tôi đoán tài liệu gần nhất về điều này là mã nguồn ...
Runium

83

Nó chủ yếu là để làm với kích thước của cửa sổ được giả định bởi thiết bị đầu cuối không giống với kích thước cửa sổ thực tế của bạn. Nếu bạn đang sử dụng bash, bạn có thể thử điều này.

$ shopt checkwinsize

Nếu bạn không nhận được

checkwinsize    on

Sau đó kích hoạt nó với

$ shopt -s checkwinsize

Sau đó, chỉ cần thử chạy một lệnh khác (như ls) hoặc thay đổi kích thước cửa sổ một lần, cách trên hoạt động với tôi mọi lúc.

Đối với các hệ thống Redhat đặc biệt, vấn đề thường xảy ra do cấu hình sai ~/.bashrckhông gọi /etc/bashrc. Thông thường, tải bash ~/.bashrcdự kiến ​​sẽ gọi /etc/bashrc, theo mặc định có chứa shopt -s checkwinsize.


Có cùng một vấn đề với OS X, rõ ràng nếu bạn gọi "đăng nhập" để khởi động thiết bị đầu cuối của mình, nó sẽ bắt đầu bash theo cách đọc / etc / bashrc, nhưng nếu bạn chỉ gọi thẳng đến bash, thì ~ / .bashrc không nguồn mặc định để bạn có được hiệu ứng gói lẻ. Cảm ơn!
rogerdpack

Cái này cũng có tác dụng với tôi. Màu sắc không có trong máy chủ cụ thể này, gọi chính xác /etc/bashrc, mọi thứ khác đều tốt ... hóa ra đây là nguyên nhân của các vấn đề gói.
dhaupin


Trông giống như một giải pháp tốt. Nhưng nó không hoạt động trong phiên ssh của tôi, mặc dù. Không chắc chắn lý do tại sao. Tôi đã chạy lệnh shopt -s checkwinsizetrong phiên ssh. Nhưng sự bao bọc vẫn tồn tại.
Qiang Xu

Đây chính xác là vấn đề của tôi - một người dùng .bashrc đã không gọi / etc / bashrc, và do đó làm cho một mớ hỗn độn.
Sobrique

9

Như đã đề cập trong các câu trả lời khác, các trình tự không in được như \e[0;30mđược gói bằng \[...\].

Thêm vào đó (và những gì tôi không thấy đề cập chưa) là có vẻ như rằng \r\nnên bên ngoài của \[...\]nếu bạn có một dấu nhắc nhiều đường. Tôi đã mất một số thử nghiệm và lỗi để cuối cùng tìm ra điều đó.


8

Tôi đã từng đọc ở đâu đó (không biết ở đâu nữa) rằng sử dụng \001\002thay vì \[\]có thể giải quyết vấn đề này. Nó đã làm cho tôi.

Nhân tiện, định nghĩa PS1 không phải trông xấu xí.

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
PS1 của tôi gọi một lệnh in chuỗi thoát thoát gây ra sự cố của OP. Chỉ có giải pháp này khắc phục vấn đề cho tôi.
RickMeasham

6

Điều này có vẻ như là một vấn đề với các thiết lập biến COLUMNS& LINESmôi trường của bạn . Khi bạn thay đổi kích thước cửa sổ, chúng thường được thiết lập tự động bởi gnome-terminal (tôi tin), bạn có thể buộc chúng được đặt thủ công bằng cách ban hành lệnh resize.

Thí dụ

Nếu tôi thay đổi kích thước thiết bị đầu cuối gnome của mình thành 79x17, các biến của tôi sẽ hiển thị như vậy:

$ echo $COLUMNS; echo $LINES
79
17

Tôi có thể buộc nó như vậy:

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

1
Thú vị, nhưng không giúp được gì.
Muricula

1
Điều này đã khắc phục sự cố của tôi, đó không phải là dòng chính xác sau khi tôi chạy lệnh "màn hình". Cảm ơn!!
nukeguy

5

Để ngăn gói, bạn cũng có thể tăng số lượng cột bằng cách sử dụng, ví dụ:

stty columns 120

1
không phải là một ý tưởng hay, nó đã làm rối tung vim một cách tàn nhẫn
phil294

3

Ngoài ra vấn đề tương tự có thể được gây ra bằng cách sử dụng các ký hiệu unicode rộng (như từ https://stackoverflow.com/a/34812608/1657819 ). Dưới đây là đoạn mã gây ra vấn đề (tâm $Green$Redđược thoát đúng chuỗi màu):

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 không thể tính toán độ dài một cách chính xác, vì vậy cách dễ nhất có thể là thoát khỏi 2 trong ba phần của các biểu tượng rộng đó.

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

Có ý nghĩa. Những gì tôi đoán là bash đếm nhân vật. Bởi vì X lấy một char nhưng được viết là 3, sau đó một người cần phải đóng 2 trong số chúng để sửa lỗi đếm. Câu trả lời @blauhirn cũng giải thích cách thực hiện trong một hàm với \001\002.
akostadinov

FYI, đây là cách bạn tìm ra cách xuất các ký tự unicode nhiều byte theo định dạng này: stackoverflow.com/a/602924/520567
akostadinov
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.