- Вопрос или проблема
- date +'%:z %Z'
- Используя переменные окружения
- Используя Systemd версии >= 241
- Используя Systemd и sed
- Используя /etc/timezone
- Используя GNU realpath поскольку /etc/localtime является символической ссылкой
- Ой! /etc/localtime не является символической ссылкой; используя find, sed, md5sum
- Используя curl и геолокацию
- Ответ или решение
- 1. Использование переменной окружения TZ
- 2. Команда date
- 3. Использование timedatectl
- 4. Проверка файла /etc/timezone
- 5. Сравнение файла /etc/localtime
- 6. Использование геолокации
- Заключение
Вопрос или проблема
Есть ли способ проверить, в каком часовом поясе я нахожусь на Linux?
Обычно переменная окружения TZ
даст вам что-то полезное. Однако лучше использовать функции, такие как mktime()
и localtime()
, для преобразования между time_t
и представлением локального часового пояса. То есть, не пытайтесь сделать преобразование самостоятельно.
Если вы имеете в виду из терминала, просто введите:
date +%Z
Если вам нужен числовой часовой пояс:
date +'%:z %Z'
Пример вывода:
-05:00 EST
Я хотел найти часовой пояс в формате “US/Eastern” или “Europe/London”. Вы можете найти это в:
- /etc/timezone (присутствует на Ubuntu и Red Hat? но не, например, на Amazon Linux)
- (на системах в стиле Red Hat) как
ZONE="US/Eastern"
в /etc/sysconfig/clock -
или вы можете попробовать сопоставить /etc/localtime с одним из файлов под /usr/share/zoneinfo; раздражает, что это, похоже, не символическая ссылка, но вы можете, например,
cd /usr/share/zoneinfo
find * -type f -exec sh -c “diff -q /etc/localtime ‘{}’ > /dev/null && echo {}” \;чтобы найти соответствующие файлы – вероятно, есть более простые способы сделать это, но это сработает. Будут несколько совпадений.
Иногда вы можете искать канонический часовой пояс, а не сокращенный вариант, как выдает date %Z
, например, US/Eastern
. На системах с timedatectl
, например, Fedora, timedatectl
выводит множество полезной информации, включая текущую зону:
# timedatectl
Местное время: Вт 2016-09-13 17:10:26 EDT
Всемирное время: Вт 2016-09-13 21:10:26 UTC
Время RTC: Вт 2016-09-13 21:10:26
Часовой пояс: US/Eastern (EDT, -0400)
Время сети включено: да
Синхронизировано по NTP: да
RTC в локальном TZ: нет
К сожалению, timedatectl
принимает set-timezone
как команду, но не имеет соответствующей get-timezone
. Разберите его следующим образом:
# timedatectl status | grep "zone" | sed -e 's/^[ ]*Time zone: \(.*\) (.*)$/\1/g'`
US/Eastern
Для systemd >= 241, смотрите @Ответ BurninateSE (TLDR: timedatectl show --va -p Timezone
).
Для ubuntu попробуйте следующее:
$ cat /etc/timezone
Пример вывода:
Asia/Kolkata
Для других дистрибутивов ссылка: https://unix.stackexchange.com/questions/110522/timezone-setting-in-linux
Для определения часового пояса вы можете использовать геолокацию:
$ curl https://ipapi.co/timezone
America/Chicago
Или:
$ curl http://ip-api.com/line?fields=timezone
America/Chicago
Все приведенные ниже решения дадут вам IANA совместимый идентификатор часового пояса Olson (например, America/Los_Angeles
). Тем не менее, некоторые из них могут возвращать лишние пробелы в начале и/или в конце – удалите их, если это необходимо.
Используя переменные окружения
Переменная окружения TZ
(если установлена) определяет часовой пояс. Проверка этого в первую очередь необходима.
$ echo $TZ
Я могу лично подтвердить, что это работает на ВСЕХ моих современных Linux-хостах.
Используя Systemd
версии >= 241
Это предпочтительный метод для всех, кто считает, что Systemd должен править миром.
$ timedatectl show --va -p Timezone
Если вы получите ошибку, подобную timedatectl: недопустимый параметр -- 'p'
, это означает, что ваш Systemd не готов править миром. Вместо этого…
Используя Systemd
и sed
Улучшение ответа Рамана, но без бесполезного использования grep. Это решение оптимально на системах с более старыми версиями Systemd.
$ timedatectl | sed -n 's/^\s*Time zone: \(.*\) (.*/\1/p'
Используя /etc/timezone
Это простой читаемый файл, но, похоже, он больше не доступен на большом количестве дистрибутивов. Если я правильно помню, это то, что разработчики Debian придумали некоторое время назад, но это вышло из моды.
$ cat /etc/timezone
Используя GNU realpath
поскольку /etc/localtime
является символической ссылкой
Это решение оптимально, если вы знаете, что /etc/localtime
является символической ссылкой, что делают как старые программные решения, так и современные руководства; и у вас также есть GNU realpath, который должен быть доступен на каждом дистрибутиве GNU OS.
$ realpath --relative-to /usr/share/zoneinfo /etc/localtime
Ой! /etc/localtime
не является символической ссылкой; используя find
, sed
, md5sum
Если вы обнаружите, что /etc/localtime
не является символической ссылкой (команда, показанная выше, либо выдаст ошибку, либо предоставит путь, начинающийся с ../
), вы можете попробовать найти его md5-совпадение в вашей локальной базе данных часовых поясов. Это может вернуть несколько совпадений, так как в базе данных Olson есть множество псевдонимов.
$ find /usr/share/zoneinfo -type f -exec md5sum {} + |\
sed /$(printf $(md5sum /etc/localtime))/'!d;s/.\{54\}//;/^posix/d'
Если вы хотите получить только один идентификатор часового пояса (любой, который вернет система readdir()), вы можете использовать команду q
в sed, чтобы выйти после первого совпадения. Это намного эффективнее, чем запускать head
, например. Однако это вызывает сбой find
на пайпе с md5sum
раньше, что приводит к выводу ошибки на fd 2. Вы можете игнорировать эту ошибку, передав ее в /dev/null, как показывает следующая полная команда:
$ find /usr/share/zoneinfo -type f -exec md5sum {} + 2> /dev/null |\
sed /$(printf $(md5sum /etc/localtime))/'!d;s/.\{54\}//;/^posix/d;q'
Используя curl
и геолокацию
Если по какой-то причине вы не хотите или не доверяете конфигурации хоста (или просто не любите его), но вы уверены, что он может подключаться к более широкому интернету, существует несколько бесплатных онлайн-сервисов, которые могут вас геолокализировать (пока они еще работают). Ниже приведены некоторые примеры:
$ curl -Lsf https://ipapi.co/timezone # Неактивный?
$ curl -Lsf http://ip-api.com/line?fields=timezone
$ curl -Lsf https://ipwhois.app/line/?objects=timezone
$ curl -Lsf http://api.ipgeolocation.io/timezone -e ';auto' | jq -r .timezone
Первые два сервиса без стыда украдены из ответа Стивена Пенни. Кроме того, я призываю сообщество SE поддерживать этот список актуальным с работающими ссылками, спасибо!
Также обратите внимание, что хотя эти сервисы бесплатны, пожалуйста, посетите их соответствующие веб-сайты, чтобы узнать о и принять их условия перед использованием.
PS наконец, пожалуйста, не используйте этот метод, чтобы связывать своих пользователей и красть их возможности – используйте этот метод только если они просят вас сделать это!
$ strings /etc/localtime | tail -n 1
MST7MDT,M3.2.0,M11.1.0
Итак, я в горном времени.
Хотя приведенные выше советы по использованию переменной окружения или просто выводу команды date иногда работают лучше, в зависимости от того, как вы хотите это использовать.
У меня Linux Mint Cinnamon.
timedatectl
дал мне нужную информацию:
Местное время: Пн 2020-06-29 11:04:27 PDT
Всемирное время: Пн 2020-06-29 18:04:27 UTC
Время RTC: Пн 2020-06-29 18:04:27
Часовой пояс: America/Vancouver (PDT, -0700)
Системные часы синхронизированы: да
Активна служба systemd-timesyncd.service: да
RTC в локальном TZ: нет
- /etc/sysconfig/clock устанавливает, сохраняется ли аппаратное время как UTC или местное время.
- Символическая ссылка /etc/localtime на /usr/share/zoneinfo/… для установки вашего часового пояса.
- Введите
/sbin/hwclock --systohc [--utc]
, чтобы установить аппаратные часы.
Ядро Linux всегда хранит и вычисляет время как количество секунд с полуночи 1 января 1970 года UTC, независимо от того, хранится ли ваше аппаратное время как UTC или нет. Преобразования в ваше местное время выполняются во время выполнения. Одна интересная вещь в этом заключается в том, что если кто-то использует ваш компьютер из другого часового пояса, он может установить переменную окружения TZ, и все даты и времена будут отображаться правильно для их часового пояса.
Если количество секунд с 1 января 1970 года UTC хранится как знаковое 32-разрядное целое (как это происходит в вашей системе Linux/Intel), ваши часы перестанут работать в какой-то момент в 2038 году. У Linux нет проблем Y2K, но он имеет проблему года 2038. Надеюсь, к тому времени мы все будем использовать Linux на 64-разрядных системах. 64-разрядные целые числа будут поддерживать наши часы довольно хорошо до примерно 292271 миллионов.
Использование TZ или date НЕ ЯВЛЯЕТСЯ НАДЕЖНЫМ, поскольку они сообщают вам часовой пояс ПОЛЬЗОВАТЕЛЯ, а не часовой пояс системы по умолчанию.
Часовой пояс системы по умолчанию хранится в /etc/timezone (который часто является символической ссылкой на файл данных часового пояса, специфичный для часового пояса). Если у вас нет /etc/timezone, посмотрите в /etc/localtime. Обычно это “серверный” часовой пояс. /etc/localtime часто является символической ссылкой на файл часового пояса в /usr/share/zoneinfo. Этот путь к правильному файловому часовому поясу также часто подсказывает географическую информацию.
Новые версии Linux имеют “timedatectl”, который дает множество информации при выполнении команды.
(в качестве примечания, если у вас есть древняя система, которая все еще использует СТАРЫЕ жестко закодированные часовые пояса, вы, вероятно, можете скопировать современный файл часового пояса на нее, и это будет работать. Мне приходилось делать это много раз, чтобы разрешить изменения часовых поясов на старом оборудовании).
Парочка решений:
date +"%Z %z"
timedatectl | grep "Time zone"
cat /etc/timezone
дали мне (соответственно):
UTC +0000
Часовой пояс: Etc/UTC (UTC, +0000)
Etc/UTC
Мой компьютер находится на UTC.
Systemd добавил больше опций, так что я не должен много использовать grep, sed или awk:
$ timedatectl show -p Timezone --value
Europe/Berlin
Это работает на Debian Buster (systemd 241), но не на Ubuntu 18.04 Bionic (systemd 237). Поэтому я теперь использую это в скриптах, чтобы сохранить это простым и чистым:
$ timedatectl show -p Timezone --value || cat "/etc/timezone"
Europe/Berlin
Иногда timedatectl set-timezone
не обновляет /etc/timezone
, поэтому лучше получить часовой пояс из имени файла, на который указывает символическая ссылка /etc/timezone
:
#!/bin/bash
set -euo pipefail
if filename=$(readlink /etc/localtime); then
# /etc/localtime является символической ссылкой, как ожидалось
timezone=${filename#*zoneinfo/}
if [[ $timezone = "$filename" || ! $timezone =~ ^[^/]+/[^/]+$ ]]; then
# не указывает на ожидаемое местоположение или не Регион/Город
>&2 echo "$filename указывает на неожиданное местоположение"
exit 1
fi
echo "$timezone"
else # сравните файлы по содержимому
# https://stackoverflow.com/questions/12521114/getting-the-canonical-time-zone-name-in-shell-script#comment88637393_12523283
find /usr/share/zoneinfo -type f ! -regex ".*/Etc/.*" -exec \
cmp -s {} /etc/localtime \; -print | sed -e 's@.*/zoneinfo/@@' | head -n1
fi
Ссылки: в этом ответе.
Вы можете показать дату и часовой пояс одновременно:
date +'%d/%m/%Y %H:%M:%S [%:z %Z]'
.
Ответ или решение
Чтобы проверить, в каком часовом поясе вы находитесь в операционной системе Linux, можно воспользоваться несколькими простыми и эффективными методами. Ниже мы подробно рассмотрим эти методы, их преимущества и особенности.
1. Использование переменной окружения TZ
Первый способ — это проверить переменную окружения TZ
, которая может сообщить о текущем часовом поясе. Выполните следующую команду в терминале:
echo $TZ
Если переменная установлена, она отобразит используемый часовой пояс. Однако, имейте в виду, что этот способ может быть ненадежен, так как он отображает только пользовательский часовой пояс.
2. Команда date
Команда date
— один из самых простых способов узнать текущий часовой пояс. Для этого выполните команду:
date +%Z
Для получения числового значения часового пояса выполните:
date +'%:z %Z'
Пример вывода:
-05:00 EST
3. Использование timedatectl
Если ваша система использует systemd
, вы можете воспользоваться командой timedatectl
, которая предоставляет актуальную информацию о времени и часовом поясе. Для получения подробной информации выполните:
timedatectl
Вывод будет содержать такие сведения, как локальное время, универсальное время и часовой пояс. Чтобы получить только значение часового пояса, используйте следующую команду:
timedatectl show -p Timezone --value
Для систем с более старыми версиями systemd
, где указанная команда может не поддерживаться, можно использовать альтернативный метод:
timedatectl | grep "Time zone"
4. Проверка файла /etc/timezone
На системах, таких как Ubuntu, вы можете обратиться к файлу /etc/timezone
, где обычно хранится информация о часовом поясе:
cat /etc/timezone
5. Сравнение файла /etc/localtime
Файл /etc/localtime
обычно является символьной ссылкой на файл в директории /usr/share/zoneinfo
, который соответствует вашему текущему часовому поясу. В случае если localtime
не является симлинком, можно выполнить команду:
find /usr/share/zoneinfo -type f -exec md5sum {} + | \
sed /$(printf $(md5sum /etc/localtime))/'!d;s/.\{54\}//;/^posix/d'
6. Использование геолокации
Если вы хотите узнать часовой пояс без обращения к конфигурациям системы, можно воспользоваться сервисами геолокации. Например:
curl https://ipapi.co/timezone
или
curl http://ip-api.com/line?fields=timezone
Заключение
Каждый из вышеперечисленных методов предоставляет актуальную информацию о текущем часовом поясе в Linux. Команда timedatectl
является самой полной и предпочтительной, предоставляя широкий спектр информации, включая поддержку и автоматическое обновление. Используйте метод, который наилучшим образом соответствует вашим нуждам и особенностям вашей системы.
Не забывайте, что правильная настройка часового пояса важна для многих приложений и можно избежать потенциальных проблем с временем, особенно в распределённых системах.