我使用的是 UB 16.04 LTS 服务器,昨天更新了区域设置-软件包已发布并安装:
Start-Date: 2019-02-21 09:44:05
Commandline: /usr/bin/apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold dist-upgrade
Upgrade: [...], locales:amd64 (2.23-0ubuntu10, 2.23-0ubuntu11), [...]
End-Date: 2019-02-21 09:44:45
windows-1252
另外,由于历史原因,我还使用依赖字符集的数据库 PostgreSQL 11 :
Name | Owner | Encoding | Collate | Ctype | Access[...]
------+----------+----------+--------------+--------------+--------------
[...] | postgres | WIN1252 | de_DE.CP1252 | de_DE.CP1252 |
为了使其可用,使用以下命令:
localedef -f CP1252 -i /usr/share/i18n/locales/de_DE /usr/lib/locale/de_DE.CP1252
使用locale-gen
before/afterlocaledef
会出现以下错误:
locale-gen de_DE.CP1252
Error: 'de_DE.CP1252' is not a supported language or locale
该错误消息是正确的,该文件/usr/share/i18n/SUPPORTED
不包含我的语言环境。据我所知,这就是我需要使用的原因localedef
。
现在的问题是,很可能在locales
安装了新的包之后,我手动添加的包被自动删除,并且依赖该语言环境的数据库的访问失败:
2019-02-21 09:42:45.109 CET [27039] FATAL: Datenbank-Locale ist inkompatibel mit Betriebssystem
2019-02-21 09:42:45.109 CET [27039] DETAIL: Die Datenbank wurde mit LC_COLLATE »de_DE.CP1252« initialisiert, was von setlocale() nicht erkannt wird.
据我了解,所有被识别和启用的区域设置dpkg-reconfigure locales
都已保留,而我的自定义区域设置未列在其中。因此,我按照说明/etc/locale.gen
创建了以下文件,其中包含以下行:
/usr/local/share/i18n/SUPPORTED
de_DE.CP1252 CP1252
最终,我的语言环境变得可用:
问题是,这似乎不足以解决我的目标:每当我运行 时dpkg-reconfigure locales
,使用 创建的语言环境localedef
就会从文件夹中删除/usr/lib/locale/de_DE.CP1252
,并且 Postgres 再次失败。即使locale -a
打印了我的语言环境等。所以这很可能是在安装新 -package 时/之后发生的情况locales
。如果我localedef
再次按照上述说明手动运行,Postgres 会立即再次允许访问旧数据库。
我注意到一件有趣的事情,就是语言环境像我的自定义语言环境一样C.UTF-8
可用/usr/lib/locale
,但由于某种原因,它永远不会被自动删除。在网上搜索该语言环境,似乎它是作为某个软件包的一部分由发行版提供的,而不是根据需要在本地配置和生成的:
我们现在有一个“可卸载”的 C.UTF-8 语言环境,即使您删除语言环境存档或更改为语言环境存档安装的语言设置,它仍然可用。
https://bugzilla.redhat.com/show_bug.cgi?id=902094#c20
/usr/lib/locale/C.UTF-8/LC_ADDRESS
/usr/lib/locale/C.UTF-8/LC_COLLATE
https://packages.debian.org/de/sid/sh4/libc-bin/filelist
那么,我需要做什么才能使我的localedef
结果存活下来,或者在安装新的包dpkg-reconfigure locales
期间所做的一切`locales
谢谢!
答案1
这里有不同的事情需要注意:
删除 localedef 的结果
手动创建的结果localedef
总是被删除,只是因为locale-gen
是一个脚本这样做:
if [ -z "$1" ] && [ -z "$KEEP" ]; then
# Remove all old locale dir and locale-archive before generating new
# locale data.
rm -rf /usr/lib/locale/locale-archive || true
for dir in /usr/lib/locale/*; do
[ -e "$dir" ] || continue
if [ "${dir#/usr/lib/locale/}" = C.UTF-8 ]; then
# owned by libc-bin
continue
fi
rm -rf "$dir" 2>/dev/null || true
done
fi
为了避免这种情况,确实需要以不同的方式提供语言环境,以便在生成语言环境时始终生成它。
/usr/local/share/i18n/SUPPORTED
该文件实际上是使我的语言环境可用的正确方法,并且我添加它的方式也正确。该行de_DE.CP1252 CP1252
导致使用与手动dpkg-reconfigure locales
使用相同的语言环境localedef
。唯一的区别是,在第一种情况下,语言环境被添加到文件中/usr/lib/locale/locale-archive
,而后者创建单独的目录。这种差异导致以下问题...
Postgres 无法识别更改
在执行测试后,我根本没有重新启动 Postgres,dpkg-reconfigure locales
但这是必要的!
当使用 where 创建的单个目录localedef
被删除或添加时,只要创建了使用该语言环境的数据库会话,Postgres 就会立即识别出来。这就是为什么我认为语言环境总是根据需要读取,但事实似乎并非如此。相反,我猜想存档文件每个进程只打开一次,并且只有当其中找不到某个语言环境时,才会识别其他目录,并且是按需的。因此,当存档文件被删除并新建时,Postgres 根本无法识别,并且仍然使用旧内容,而旧内容从未包含我的语言环境。
重新启动 Postgres 后,使用嵌入了我所在语言环境的新存档文件,一切又恢复正常。dpkg-reconfigure locales
只需再次运行删除我的语言环境即可轻松重现此问题,无需重新启动 Postgres,它就会继续工作。重新启动后,它会再次失败,直到语言环境再次添加到存档文件中。
不使用 localedef?
因此,看来最终使结果localedef
存活下来的正确方法是不要手动使用,而是在文件中定义所需的语言环境,在最坏的情况下重新启动系统。dpkg-reconfigure locales
localedef
/usr/local/share/i18n/SUPPORTED