Я использую сервер 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
Я дополнительно использую PostgreSQL 11 с базами данных, использующими набор символов windows-1252
по историческим причинам:
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
до после localedef
дает следующую ошибку:
locale-gen de_DE.CP1252
Error: 'de_DE.CP1252' is not a supported language or locale
Это сообщение об ошибке правильное, файл /usr/share/i18n/SUPPORTED
не содержит мою локаль. Насколько я понимаю, поэтому мне нужно использовать localedef
.
Проблема сейчас в том, что, скорее всего, после нового locales
-package был установлен, добавленный мной вручную был удален автоматически, и доступ к базам данных, основанным на этой локали, не удался:
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
печатает мою локаль и все такое. Так что, скорее всего, что происходило с / после установки нового locales
-пакет. Если я сбегу localedef
как описано выше снова вручную, Postgres мгновенно снова открывает доступ к устаревшим базам данных.
Одна интересная вещь, которую я узнал, - это регион C.UTF-8
быть доступным в /usr/lib/locale
как и мой собственный, НО по какой-то причине он никогда не удаляется автоматически. При поиске этой локали в Интернете кажется, что она предоставляется как часть некоторого пакета дистрибутивом, а не настраивается и генерируется локально по мере необходимости:
Теперь у нас есть "удаляемая" локаль C.UTF-8, которая доступна, даже если вы удалите locale-archive или измените установленный язык, установленный для locale-archive.
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
-пакеты`
Спасибо!
Здесь следует отметить разные моменты:
Созданные вручную результаты 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
Чтобы обойти это, действительно нужно сделать локаль доступной по-другому, чтобы она генерировалась всегда, когда локали вообще генерируются.
Этот файл на самом деле является правильным способом сделать мою локаль доступной, и то, как я ее добавил, ЯВЛЯЕТСЯ правильным. Линия de_DE.CP1252 CP1252
приводит к созданию той же локали с использованием dpkg-reconfigure locales
нравится использовать localedef
вручную. Единственное отличие состоит в том, что в первом случае в файл добавляется локаль. /usr/lib/locale/locale-archive
, а последний создает отдельные каталоги. Это различие приводит к следующей проблеме ...
Я просто никогда не перезапускал Postgres во время тестов после выполнения dpkg-reconfigure locales
и это необходимо!
Когда отдельные каталоги, созданные с использованием localedef
там, где это было удалено или добавлено, Postgres распознал это мгновенно, когда бы ни был создан сеанс с базой данных, использующий этот языковой стандарт. Вот почему я думал, что языковые стандарты всегда читаются по мере необходимости, но, похоже, это не так. Вместо этого я предполагаю, что файл архива открывается только один раз для каждого процесса, и только если какой-либо языковой стандарт не найден там, дополнительные каталоги распознаются и по запросу. Поэтому, когда файл архива был удален и создан заново, Postgres просто не распознал и продолжал работать со старым содержимым, которое никогда не содержало мою локаль.
После перезапуска Postgres, который использовал новый архивный файл с моей встроенной локалью, все снова заработало. Это легко воспроизвести, запустив dpkg-reconfigure locales
чтобы снова удалить мою локаль, и без перезапуска Postgres он просто продолжит работать. После перезапуска он снова не работает, пока языковой стандарт снова не будет добавлен в файл архива.
Так что кажется правильным подходом к получению результатов localedef
выжить dpkg-reconfigure locales
в конце концов, НЕ использовать localedef
вручную, но вместо этого определите необходимый языковой стандарт в файле /usr/local/share/i18n/SUPPORTED
и в худшем случае перезагрузить систему.