linux-labs

Вики / Базовые команды

Локаль и кодировка (locale)

Концепция Ubuntu 24.04 БазовоеТекст и потоки

Язык, кодировка и форматы — LANG/LC_*, генерация локалей, проблемы с UTF-8.

Локаль задаёт язык, кодировку и форматы (даты, числа, сортировка) — через переменные окружения $LANG/$LC_*. На серверах важна прежде всего кодировка: для корректного UTF-8 нужна *.UTF-8 локаль.

locale                            # текущие настройки локали
locale -a                         # какие локали установлены
echo $LANG                        # основная переменная
sudo locale-gen en_US.UTF-8 ru_RU.UTF-8   # сгенерировать локали
sudo update-locale LANG=en_US.UTF-8       # системная локаль по умолчанию (/etc/default/locale)
# временно в текущей сессии:
export LANG=ru_RU.UTF-8

localectl status                  # системная локаль (systemd)
sudo localectl set-locale LANG=en_US.UTF-8
sudo dpkg-reconfigure locales     # интерактивный выбор (Debian/Ubuntu)

Иерархия: LC_ALL (перебивает всё) > конкретные LC_* > LANG (общий дефолт).

Переменная На что влияет
LANG общий дефолт для всех категорий
LC_CTYPE кодировка (UTF-8!)
LC_TIME формат даты/времени (см. date)
LC_NUMERIC десятичный разделитель (. или ,)
LC_COLLATE порядок сортировки (sort)
LC_ALL перебивает всё (для скриптов: LC_ALL=C)

Кракозябры вместо кириллицы/символов

Не UTF-8 локаль или терминал. Проверь locale (должно быть *.UTF-8), сгенерируй (locale-gen), и что терминал/SSH в UTF-8.

warning: setlocale: LC_*: cannot change locale

Запрошенная локаль не сгенерирована. sudo locale-gen <локаль>; убедись, что она в locale -a. Частое по SSH: клиент шлёт LC_* (через SendEnv), а на сервере её нет — либо сгенерируй, либо убери приём (AcceptEnv в sshd).

Скрипт по-разному сортирует/парсит на разных машинах

Локаль влияет на sort, числа, даты. Для предсказуемости: export LC_ALL=C (байтовая сортировка, точка как десятичный разделитель). Часто ставят в начале скриптов.

Дата/числа в «неожиданном» формате

LC_TIME/LC_NUMERIC. Зафиксируй нужную локаль или LC_ALL=C для машинного вывода. Разово: LC_ALL=C sort file, LC_TIME=ru_RU.UTF-8 date.

perl: warning setting locale failed

Часто безвредно, но раздражает: на сервере нет локали, переданной по SSH. Лечится генерацией нужной локали или AcceptEnv-фильтром.

locale ; locale -a                # текущая / доступные
sudo locale-gen ru_RU.UTF-8       # сгенерировать
sudo update-locale LANG=en_US.UTF-8   # системная (или localectl set-locale)
export LC_ALL=C                   # стабильный вывод в скриптах
LC_ALL=C sort file                # разовая байтовая сортировка
localectl status                  # systemd-вид

См. также