Назад | Перейти на главную страницу

Как сделать так, чтобы результаты «localedef» пережили «dpkg-reconfigure locales»?

Я использую сервер 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

Созданные вручную результаты 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 / ПОДДЕРЖИВАЕТСЯ

Этот файл на самом деле является правильным способом сделать мою локаль доступной, и то, как я ее добавил, ЯВЛЯЕТСЯ правильным. Линия de_DE.CP1252 CP1252 приводит к созданию той же локали с использованием dpkg-reconfigure locales нравится использовать localedef вручную. Единственное отличие состоит в том, что в первом случае в файл добавляется локаль. /usr/lib/locale/locale-archive, а последний создает отдельные каталоги. Это различие приводит к следующей проблеме ...

Postgres не распознает изменения

Я просто никогда не перезапускал Postgres во время тестов после выполнения dpkg-reconfigure locales и это необходимо!

Когда отдельные каталоги, созданные с использованием localedef там, где это было удалено или добавлено, Postgres распознал это мгновенно, когда бы ни был создан сеанс с базой данных, использующий этот языковой стандарт. Вот почему я думал, что языковые стандарты всегда читаются по мере необходимости, но, похоже, это не так. Вместо этого я предполагаю, что файл архива открывается только один раз для каждого процесса, и только если какой-либо языковой стандарт не найден там, дополнительные каталоги распознаются и по запросу. Поэтому, когда файл архива был удален и создан заново, Postgres просто не распознал и продолжал работать со старым содержимым, которое никогда не содержало мою локаль.

После перезапуска Postgres, который использовал новый архивный файл с моей встроенной локалью, все снова заработало. Это легко воспроизвести, запустив dpkg-reconfigure locales чтобы снова удалить мою локаль, и без перезапуска Postgres он просто продолжит работать. После перезапуска он снова не работает, пока языковой стандарт снова не будет добавлен в файл архива.

Не использовать localedef?

Так что кажется правильным подходом к получению результатов localedef выжить dpkg-reconfigure locales в конце концов, НЕ использовать localedef вручную, но вместо этого определите необходимый языковой стандарт в файле /usr/local/share/i18n/SUPPORTED и в худшем случае перезагрузить систему.