방금 문제가 발생했습니다. Linux 시스템을 다시 시작할 때 마운트된 VFAT 파일 시스템에 있는 모든 파일의 타임스탬프가 잘못된 시간대로 표시됩니다. 장치는 현지 시간이 UTC라고 생각하기 시작하여 모든 타임스탬프를 오프셋과 함께 표시합니다.
재현 단계:
작은 FAT 형식 이미지를 만듭니다.
dd if=/dev/zero of=small.img bs=1M seek=1 count=0
mkfs.vfat small.img
이 이미지를 로컬로 마운트합니다.
mount -t vfat -o umask=0022,gid=1001,uid=1001 small.img mnt
시간대를 UTC가 아닌 시간대로 설정합니다.
마운트된 파일 시스템(예:
touch mnt/newfile
) 에 파일을 생성합니다.파일 수정/변경 타임스탬프를 관찰하세요. 현재 설정된 타임스탬프에 대해 정확합니다.
stat mnt/newfile
File: mnt/newfile Size: 0 Blocks: 0 IO Block: 16384 regular empty file Device: 700h/1792d Inode: 40 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2021-03-22 12:19:56.000000000 +0100 Modify: 2021-03-22 12:19:56.000000000 +0100 Change: 2021-03-22 12:19:56.000000000 +0100 Birth: -
timedatectl
Local time: Mon 2021-03-22 12:19:07 CET Universal time: Mon 2021-03-22 11:19:07 UTC RTC time: Mon 2021-03-22 11:19:07 Time zone: Europe/Vienna (CET, +0100) System clock synchronized: yes NTP service: active RTC in local TZ: no
파일 시스템을 마운트 해제하고 다시 마운트하여 변경 사항이 있는지 확인합니다.
umount mnt; mount -t vfat -o umask=0022,gid=1001,uid=1001 small.img mnt; stat mnt/newfile
File: mnt/newfile Size: 0 Blocks: 0 IO Block: 16384 regular empty file Device: 700h/1792d Inode: 64 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2021-03-22 00:00:00.000000000 +0100 Modify: 2021-03-22 12:19:56.000000000 +0100 Change: 2021-03-22 12:19:56.000000000 +0100 Birth: -
시스템을 다시 시작하십시오.
이미지를 다시 마운트하고 생성된 파일의 타임스탬프를 확인하세요.
File: mnt/newfile Size: 0 Blocks: 0 IO Block: 16384 regular empty file Device: 700h/1792d Inode: 26 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2021-03-22 01:00:00.000000000 +0100 Modify: 2021-03-22 13:19:56.000000000 +0100 Change: 2021-03-22 13:19:56.000000000 +0100 Birth: -
시간이 1시간(12:10에서 13:19) 앞당겨진 것을 확연히 알 수 있는데, 시간대는 동일하게 +0100으로 표시됩니다. mount
이제 파일 타임스탬프가 UTC로 기록된다고 생각하여 "올바른" 오프셋을 사용하여 표시하려고 시도하는 것 같습니다 .
이전 명령문의 유효성을 확인하려면 tz=UTC
이 옵션을 명시적으로 사용하여 동일한 파일 시스템을 다시 마운트해 보겠습니다.
mount -t vfat -o umask=0022,gid=1001,uid=1001,tz=UTC small.img mnt; stat mnt/newfile
File: mnt/newfile
Size: 0 Blocks: 0 IO Block: 16384 regular empty file
Device: 700h/1792d Inode: 50 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2021-03-22 01:00:00.000000000 +0100
Modify: 2021-03-22 13:19:56.000000000 +0100
Change: 2021-03-22 13:19:56.000000000 +0100
Birth: -
시스템의 시간대가 실제로 CET인 경우에도:
date
Mon Mar 22 12:26:42 CET 2021
폴리스티렌https://stackoverflow.com/questions/10068855/how-do-i-get-the-Cordirect-modified-datetime-of-a-fat32-file-regardless-of-timezo답변을 얻을 수 없기 때문에 이 질문에 대한 답변이 아닙니다. 재설치 직후가 아니라 컴퓨터를 다시 시작한 직후에 이 변경 사항이 표시되는 이유는 무엇입니까? vfat가 타임스탬프를 현지 시간으로 저장하는 경우, 재부팅 후 마운트에서 타임스탬프가 현지 시간이 아닌 UTC라고 가정하는 이유는 무엇입니까?
답변1
리눅스 커널 자체에 문제가 있는 것 같은데,시간대는 (일반적으로) 커널과 사용자 공간 간에 다를 수 있습니다.. Linux 커널 소스 트리 의 파일은 time.c
저장(및 내보내기)된 다음 FAT 시간 <-> UNIX 시간 규칙에 따라 사용됩니다. 이 구조의 필드는 옵션이 다음과 같은 경우 현재 시간대와 UTC 간의 차이를 표시하는 데 사용됩니다.kernel/time
struct timezone sys_tz
fs/fat/misc.c
tz_minuteswest
tz=UTC
아니요mount.vfat
명령 에 전달되었습니다 . 그러나 위의 필드는 설명된 대로 기본적으로 0으로 설정됩니다.여기,
Linux에서는 NULL이 아닌 tz 매개변수를 사용한 첫 번째 호출에서(시작 후) tv 매개변수가 NULL이고 tz_ Minuteswest 필드가 영. (이 경우 tz_dsttime 필드는 0이어야 합니다.) 이 경우 CMOS 시계는 로컬 시간으로 간주되며 UTC 시스템 시간을 얻으려면 이 양만큼 증가해야 합니다. 이 기능을 사용하는 것이 나쁜 생각이라는 것은 의심의 여지가 없습니다.
따라서 커널(및 해당 드라이버)이 항상 올바른 시간대를 확인하도록 하는 유일한 방법은 UTC(예: -60 CET 등)를 기준으로 원하는 시간 오프셋 "서부"(시간 단위)를 사용하여 매개변수를 settimeofday()
호출 하는 것 입니다. 각 시스템 시작 후 0으로 설정됩니다. 이는 (어떤 방식으로든) 시스템 시간대를 설정하여 달성할 수 있습니다.tz
tz.tz_minuteswest
tz_dsttime
현재의시간대다른 값(예: UTC)으로 변경한 후timedatectl
, 명령줄 도구 sa는 일반적으로 원하는 시간대가 현재 시간대와 같은 경우 실제 시간대 변경을 수행하지 않기 때문입니다. 이 개념을 보여주기 위해 다음 코드를 만듭니다.
#include <sys/time.h>
#include <stdio.h>
int main()
{
struct timeval tv;
struct timezone tz;
int ret = gettimeofday(&tv, &tz);
printf("%d, %dr\n", tz.tz_minuteswest, tz.tz_dsttime);
return ret;
}
코드는 다음과 같이 실행됩니다.
$gcc testtz.cpp -o testtz
$./testtz
minuteswest: 0, dsttime: 0r
$timedatectl set-timezone Europe/Vienna
$./testtz
minuteswest: 0, dsttime: 0r
$timedatectl set-timezone UTC
$timedatectl set-timezone Europe/Vienna
$./testtz
minuteswest: -60, dsttime: 0r
timezone
구조의 사용은 더 이상 사용되지 않는 것으로 간주되지만 문제는 곧 사라지지 않습니다. 그래서 내 문제에 대해서는 사용을 고려할 것입니다.time_offset=분 옵션의 mount.vfat
.