“-bash:警告:setlocale:LC_ALL:无法更改区域设置(en_US.UTF-8)”

pat*_*t-s 6 bash prompt terminal locale

运行全新的 Ubuntu 16.04 和 Debian 8 服务器。尝试通过 ssh 连接并获得以下奇怪的终端输出。我指的是带有数字的矩形。

语言设置的问题是我自己为了解决刚才提到的问题而引入的,因为我认为一些编码问题是有责任的。经过 3 小时的调试,我需要您的帮助!

也许这只是一个缺少的图书馆?很难搜索这样的图形问题......

在此处输入图片说明

local@local:~$ ssh dummy@server

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sat Jul  9 17:22:43 2016 from x590c3909.dyn.telefonica.de
-bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
-bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
-bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
]1337;RemoteHost=dummy@server]1337;CurrentDir=/home/patrick]1337;ShellIntegrationVersion=2;shell=bash]133;C;]133;D;0]1337;RemoteHost=dummy@server]1337;CurrentDir=/home/patrick]133;Adummy@server:~$ ]133;B
Run Code Online (Sandbox Code Playgroud)

回声 $PS1 输出:

echo $PS1
]133;C;\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$
Run Code Online (Sandbox Code Playgroud)

回声 $TERM 输出:

echo $TERM
]133;C;xterm
Run Code Online (Sandbox Code Playgroud)

编辑:“语言环境” -此答案修复的警告。

Jde*_*eBP 10

你的终端在做什么

“[them] 中带有数字的矩形”是终端仿真器向您显示终端控制序列的方式,因为它无法识别该序列。具体来说:

  • 有一个 ECMA-48 控制字符(在 C1 组中,用于技术)名为操作系统命令,缩写为 OSC。它的 Unicode 值是 U+009D。
  • ECMA-48 定义了一种机制,其中需要完全干净的 8 位通信路径才能传输的 C1 组中的字符可以由仅使用值小于 U+0080 的字符的转义序列表示 (128) . 这些7 位别名允许在非 8 位干净的传输路径上使用 C1 控制字符。具有讽刺意味的是,几十年来,世界基本上是 8 位清洁的。

    您很可能知道这些非常常见的 7 位别名之一:ESC[而不是 CSI 控制字符 (U+009B)。OSC 控制字符具有 ESC]作为 7 位别名。

  • SSH 连接远端的某些东西期望您的终端理解以 OSC 开头的控制序列。它使用 7 位别名传输它们。
  • 您的终端没有完全实现 ECMA-48。它看到 ESC]并将其视为 ESC 字符后跟一个]字符。这就是它正在打印的内容。
  • 但它没有 ESC 字符的字形。因此,它退回到将没有字形的字符显示为带有 Unicode 代码点(最低 16 位)十六进制值的框的传统技巧。如果您仔细观察,您会看到数字001B方框中的 U+001B,即 ESC 字符的代码点。
  • 它也没有正确处理它为 ESC 打印的内容的“间距”,即它在屏幕上占用的空间,实际上是两个字符宽度。所以在打印盒子后,它并没有足够地推进输出位置。然后],如您所见,它会在框右半部分的顶部打印。

为什么它被告知要这样做

几个终端仿真器将 OSC 识别为控制字符序列引入器。甚至有一个标准的形式。ECMA-48 § 5.6 定义了以 OSC 开头并以 ST 结尾的“控制字符串”(U+009C,字符串终止符)。是什么控制字符串是终端类型具体。例如:您将从它的文档中看到 xterm 实现了这样的控制字符串,用于设置字体和窗口标题。

但是,这种情况下控制序列的形式不是 xterm 的形式。而是

␛]1337;CurrentDir=/home/patrick␇

这是 iTerm2 理解的 OSC 控制序列的形式。iTerm2 定义了一组由 OSC 引入的控制序列,这些控制序列与 iTerm2 明显非标准和特殊。它们不遵守 ECMA-48 控制字符串规范,而是使用 BEL (U+0007) 而不是标准所说的 ST 终止控制字符串。严格来说,这是一个永远不会终止的控制字符串,因为控制字符串的内容中允许使用除 SOS 和 ST 之外的任何字符;并且是具有一致终端仿真器的有效只是停止显示,因为终端只是将所有进一步的输出累积为控制字符串。

(内置于 Linux 内核中的终端仿真器也没有实现标准的 OSC 控制字符串。xterm doco 指出它有支持使用不符合 Linux 内核终端仿真器或 iTerm2 形式的损坏应用程序的工具。表单不过,这里绝对是 iTerm2 的,而不是 Linux 内核终端模拟器的。)

当您从 Macintosh 使用 iTerm2 时,无论 SSH 连接的另一端是什么,都会悄悄地将 iTerm2 控制序列发送到您的终端模拟器,以告诉它诸如您的 shell、您的工作目录是什么、您是谁、何时你在 shell 提示符下开始编辑,当你开始执行命令时,等等。

在远程系统上,您已经硬连线了终端类型。你已经在假设你总是用 iTerm2 与它交谈的情况下运行它。但是您现在正在使用运行在 Ubuntu 上的 Terminator 与它对话,这是一个不同的终端仿真器,具有不同的控制序列集。

事实上,输出甚至告诉你:

␛]1337;ShellIntegrationVersion=2;shell=bash␇

您已经在远程系统上为 Bourne Again shell 安装了 iTerm2“Shell Integration”。看看它,检查 iTerm2 实际上是它正在与之对话的终端是非常糟糕的。

所以禁用/卸载它。

进一步阅读

  • 编码字符集的控制函数。ECMA-48。ECMA 国际。
  • console_codes. Linux 手册页。2015 年第 4 节。
  • 马修·弗里曼、乔治·纳赫曼和詹姆斯·A·罗森。 专有转义码。iTerm2 文档。
  • 马修·弗里曼、乔治·纳赫曼和詹姆斯·A·罗森。 外壳集成。iTerm2 文档。