Linux: 대륙/도시 형식으로 시간대를 얻는 안정적인 방법

Linux: 대륙/도시 형식으로 시간대를 얻는 안정적인 방법

저는 유럽/키예프와 같은 대륙/도시 형식으로 Linux 시스템(주로 다른 버전의 데비안)의 시간대를 가져오는 이식 가능하고 강력한 방법을 찾고 있습니다.

지금까지 사용한 이 접근 방식의 문제점은 timedatectl status | grep zone | cut -d' ' -f10 Debian 9에서는 작동하지만 Debian 10에서는 작동하지 않는다는 것입니다(도커 이미지를 사용하여 쉽게 확인할 수 있습니다).

이 작업을 수행하는 더 좋고 더 일반적이고 이식 가능한 방법이 있습니까(다른 명령의 출력을 스크랩/파싱하지 않는 것이 더 좋습니다)? 그렇지 않은 경우 위 명령을 Debian 9와 10 모두에서 작동하도록 어떻게 수정해야 합니까?

답변1

timedatectl status | awk '/zone/ {print $3}'

답변2

지리적 시간대 이름은 추상적이고 편리합니다. 내부적으로 시간대 데이터 파일은 오프셋, 불연속성 및 DST 변경 사항을 나열하지만 위치는 나열하지 않는 이진 파일입니다(파일 이름이 이를 나타내더라도 문제가 발생함 /etc/localtime). 위치부터 지도가 있어요및 날짜시간대 오프셋에 적용되지만 1:1은 아닙니다. 예를 들어 출력이 주어지면 date사용 중인 지리적 위치를 쉽고 결정적으로 파생할 수 없습니다(그러나 현재 날짜에 대해 호환되는 위치 집합을 계산할 수 있습니다. 또는 다음을 사용할 수 있습니다). 약간의 노력, 위치를 추론할 수 있도록 이전 날짜에 불연속성을 확인).

하나 있다지역 이름의 마스터 목록및 시간대 정의 파일처럼 보인다:

# Zone  NAME            GMTOFF  RULES   FORMAT  [UNTIL]
Zone    Europe/London   -0:01:15 -      LMT     1847 Dec  1 0:00s
                         0:00   GB-Eire %s      1968 Oct 27
                         1:00   -       BST     1971 Oct 31 2:00u
                         0:00   GB-Eire %s      1996
                         0:00   EU      GMT/BST
Link    Europe/London   Europe/Jersey
Link    Europe/London   Europe/Guernsey
Link    Europe/London   Europe/Isle_of_Man

바이너리가 생성 되면 Europe/London표시된 규칙이 처리되어 임시 규칙(변경 사항이 발생한 타임스탬프, 비교 확인 zdump -v Europe/London)을 구축하고 관련 위치에 별칭이 지정됩니다. 위 위치의 파일 내용이나 출력은 구별할 수 없습니다 localtime.date

추상화를 사용하면 적시에 법적 변경 사항을 처리할 수 있습니다.

# TZ=Europe/Andorra date -d "Aug 31 1984"
Fri Aug 31 00:00:00 CET 1984

TZ=Europe/Andorra date -d "Aug 31 1985"
Sat Aug 31 00:00:00 CEST 1985

(안도라는 EU에 속하지 않지만 1985년부터 EU DST 규칙을 따랐습니다.)

/etc/localtime(바이너리) 시간대 데이터 파일이고 데비안에서는 관례적으로 지정된 지리적 시간대 파일에 대한 심볼릭 링크여야 합니다(다음에 따라).''긴장''(9) 그리고"버스터"(10) localtime매뉴얼 페이지:

/etc/localtime 파일은 응용 프로그램이 사용자에게 표시하기 위해 사용하는 로컬 시스템의 시스템 전체 시간대를 구성합니다. /usr/share /zoneinfo/에 대한 절대 또는 상대 심볼릭 링크여야 하며 그 뒤에 "Europe/Berlin" 또는 "Etc/UTC"와 같은 시간대 식별자가 와야 합니다. 생성된 링크는 구성된 시간대에 해당하는 이진 tzfile(5) 시간대 데이터를 가리켜야 합니다.

타임존 식별자는 /etc/localtime의 심볼릭 링크 대상 이름에서 추출되므로 파일이 일반 파일이나 하드 링크가 아닐 수 있습니다.

다음과 같은 경우를 가정해 보겠습니다.

if [ -L /etc/localtime ]; then
  IFS=/ read -a TZFILE < <(readlink -f /etc/localtime)
  printf -v TZNAME "%s/%s\n" ${TZFILE[-2]} ${TZFILE[-1]}
  echo $TZNAME
fi

이전 버전에서는(또는 누군가 문서를 따르지 않은 경우)복사시간대 데이터 파일. 그래서 이것을 확인 /etc/localtime하고 /etc/timezone당신의 의견에 동의하기 위해그것들을 비교해야 해:

$ diff -s /etc/localtime /usr/share/zoneinfo/`cat /etc/timezone`
Files /etc/localtime and /usr/share/zoneinfo/America/New_York are identical

뒤로 또는 근본적으로 이동해야 하는 경우:

read CHECK file < <(sha256sum /etc/localtime)
while read sum file; do 
  [[ "$sum" == "$CHECK" ]] && printf "%s\n" "$file"
done < <(find /usr/share/zoneinfo/ -type f |xargs sha256sum)

이것은 실제로 이식 가능한 답변이 아닙니다(POSIX는 이러한 답변을 정의하거나 요구하지 않습니다).긴 이름, ICANN/IANA에서 왔으며 systemd해당 버전의 Debian에서 명령을 사용하고 있습니다.

답변3

/etc/timezone파일에서 시간대를 가져올 수 있습니다.

cat /etc/timezone

답변4

이는 Unix와 Mac 시스템 모두에서 작동합니다.

readlink /etc/localtime | awk -F'/' '{print $(NF-1)"/"$(NF)}'

관련 정보