UTF-8 语言环境可移植性(和 ssh)

kin*_*ine 9 linux bsd shell locale utf-8

我花了很多时间ssh在各种机器上进行研究,所有机器都不同(有些是嵌入式的,有些运行 Linux,有些运行 BSD,等等)。然而,在我自己的本地机器上,我使用 OS X,它当然有一个基于 BSD 的用户空间。我在这些机器上的语言环境设置为 en_GB.UTF-8,这是可用选项之一:

% echo `sw_vers`
ProductName: Mac OS X ProductVersion: 10.8.2 BuildVersion: 12C60
% locale -a | grep -i 'en_gb.utf'
en_GB.UTF-8
Run Code Online (Sandbox Code Playgroud)

我使用的几个更强大的 Linux 系统似乎有一个等效的选项,但我注意到在 Linux 上名称略有不同:

% lsb_release -d
Description: Debian GNU/Linux 6.0.3 (squeeze)
% locale -a | grep -i 'en_gb.utf' 
en_GB.utf8
Run Code Online (Sandbox Code Playgroud)

这让我想知道:当我ssh从我的 Mac 进入一台 Linux 机器时,它LC_*使用“UTF-8”后缀转发我的所有变量,那台 Linux 机器甚至理解它的要求吗?或者它只是回退到其他地方?

编辑:这是我所指的一个例子:

% ssh -v odin
...
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env LC_ALL = en_GB.UTF-8
debug1: Sending env LC_COLLATE = en_GB.UTF-8
debug1: Sending env LC_CTYPE = en_GB.UTF-8
debug1: Sending env LC_MESSAGES = en_GB.UTF-8
debug1: Sending env LC_MONETARY = en_GB.UTF-8
debug1: Sending env LC_NUMERIC = en_GB.UTF-8
debug1: Sending env LC_TIME = en_GB.UTF-8
debug1: Sending env LANG = en_GB.UTF-8
odin:~ % locale | tail -1  # locale is set to .UTF-8 without error...
LC_ALL=en_GB.UTF-8
odin:~ % locale -a | grep 'en_GB.UTF-8'  # ... even though .UTF-8 isn't an option
odin:~ % 
Run Code Online (Sandbox Code Playgroud)

在任何一种情况下,其行为背后的机制是什么,它是否依赖于任何特定的设置(例如,我会在基于 BusyBox 的系统上看到与在基于 GNU 的系统上相同的行为吗)?

Яро*_*лин 0

这是一个有趣的问题,但我认为其中可能存在关于如何设置变量的误解。当安全 shell 会话启动 ( ssh remotehost) 时,另一端会实例化一个具有单独环境的新 shell。这是服务器启动一个新 shell 的一种奇特方式。该新 shell 可能会或可能不会配置与原始本地 shell 相同的区域设置。

例如

哎呀:~
$ echo `locale |grep LANG` :: `日期`
LANG=en_US.UTF-8 :: 2012 年欧洲中部时间 12 月 3 日星期一 07:04:00

$ ssh 洪水
洪水:〜
$ echo `locale |grep LANG` :: `日期`
LANG=nb_NO.UTF-8 LANGUAGE=nb_NO.UTF-8 :: ma. 03. 沙漠。06:59:33 +0100 2012

为了演示这一点,我通过将以下行添加到 ~/.bash_profile 文件中,在远程 shell 上设置挪威语的区域设置:

export     LANG=nb_NO.UTF-8
export LANGUAGE=nb_NO.UTF-8
export   LC_ALL=nb_NO.UTF-8
Run Code Online (Sandbox Code Playgroud)

同样,您必须在远程 shell上设置环境才能执行相同的操作。当然,其他 shell 会读取不同的启动文件,例如 Z shell 的 ~/.zprofile。

我怀疑的误解在于局部变量(设置)根本没有被转发。远程 shell 有自己的设置。为了列出远程主机上的可用语言,无论是简约的 BusyBox shell 还是成熟的 GNU 操作系统,请使用locale带有开关的命令-a(如问题中所述)。任何打印行都可以用作该环境的区域设置。

对于第一个问题,任何 shell 启动的默认语言环境通常配置在一个中心位置,例如 /etc/profile。大多数登录 shell 在启动时都会读取此文件。

  • 语言环境的内容肯定会被转发。我见过的每台机器上的“/etc/ssh_config”都定义了“LANG”和“LC_*”默认发送到所有主机,“ssh -v”显示了几行,例如“debug1: Sending env LC_ALL” = en_GB.UTF-8`。当然,如果另一端的 shell 配置文件随后覆盖了它,那就是另一回事了——但在我的某些机器上,情况并非如此 (2认同)