Timezones
Closed this issue · 18 comments
Rudimentary investigation shows that the timezone stored in the meta files is not useful for cleanup for some zones:
$ date
Tue May 7 03:44:38 UTC 2019
$ grep Timezone server.foo.com-meta-2019-05-07.tar.gz
Timezone: NZST
$ TZ=NZST date
Tue May 7 03:44:43 NZST 2019
Which gives problems with cleanup:
omnipitr-backup-cleanup : ERROR : When processing meta file (server.foo.com-meta-2019-05-07.tar.gz): $VAR1 = {
omnipitr-backup-cleanup : ERROR : 'started-epoch' => '1557181801',
omnipitr-backup-cleanup : ERROR : 'timezone' => 'NZST',
omnipitr-backup-cleanup : ERROR : 'hostname' => 'server.foo.com',
omnipitr-backup-cleanup : ERROR : 'min-xlog' => '0000000100000000000000CC',
omnipitr-backup-cleanup : ERROR : 'file_name' => 'server.foo.com-meta-2019-05-07.tar.gz'
omnipitr-backup-cleanup : ERROR : };
omnipitr-backup-cleanup : ERROR : , regenerated filename was incorrect: server.foo.com-meta-2019-05-06.tar.gz. Ignoring metafile.
Very dirty hack to work around this was to symlink the short names to NZ
:
# ls -l /usr/share/zoneinfo/NZ*
-rw-r--r-- 1 root root 2460 Mar 27 20:34 /usr/share/zoneinfo/NZ
lrwxrwxrwx 1 root root 2 May 7 03:25 /usr/share/zoneinfo/NZDT -> NZ
lrwxrwxrwx 1 root root 2 May 7 03:25 /usr/share/zoneinfo/NZST -> NZ
Which allows usage of NZST and NZDT zones:
$ date
Tue May 7 03:50:51 UTC 2019
$ TZ=NZST date
Tue May 7 15:50:52 NZST 2019
I'm guessing that something a little more robust than perl's localtime
and %Z
will be required to correctly check timestamps?
Thanks for the report. Will look into it.
I tried, but I can't replicate the problem. Are you absolutely sure, that you have NZST zoneinfo file on the server that runs omnipitr-backup-cleanup ?
Can you, please, on the server that runs omnipitr-backup-cleanup, download this script, and run it like this:
TZ=NZ ./test.pl
TZ=NZST ./test.pl
TZ=UTC ./test.pl
and provide me with outputs?
Certainly:
With NZST
/NZDT
links in place in /usr/share/zoneinfo
as a workaround to make things work, results from the test script are as expected:
root@server:/usr/share/zoneinfo# ls -l NZ{,ST,DT}
-rw-r--r-- 1 root root 2460 Mar 27 20:34 NZ
lrwxrwxrwx 1 root root 2 May 7 03:25 NZDT -> NZ
lrwxrwxrwx 1 root root 2 May 7 03:25 NZST -> NZ
root@server:/usr/share/zoneinfo# TZ=NZ ~/test.pl
Before: 1557181801 , 1 , 30 , 10 , 7 , 4 , 119 , 2 , 126 , 0 , 2019-05-07 10:30:01 +1200 NZST
After: 1557181801 , 1 , 30 , 10 , 7 , 4 , 119 , 2 , 126 , 0 , 2019-05-07 10:30:01 +1200 NZST
[server.foo.com-meta-2019-05-07.tar.gz] vs. [server.foo.com-meta-2019-05-07.tar.gz]
root@server:/usr/share/zoneinfo# TZ=NZST ~/test.pl
Before: 1557181801 , 1 , 30 , 10 , 7 , 4 , 119 , 2 , 126 , 0 , 2019-05-07 10:30:01 +1200 NZST
After: 1557181801 , 1 , 30 , 10 , 7 , 4 , 119 , 2 , 126 , 0 , 2019-05-07 10:30:01 +1200 NZST
[server.foo.com-meta-2019-05-07.tar.gz] vs. [server.foo.com-meta-2019-05-07.tar.gz]
root@server:/usr/share/zoneinfo# TZ=UTC ~/test.pl
Before: 1557181801 , 1 , 30 , 22 , 6 , 4 , 119 , 1 , 125 , 0 , 2019-05-06 22:30:01 +0000 UTC
After: 1557181801 , 1 , 30 , 10 , 7 , 4 , 119 , 2 , 126 , 0 , 2019-05-07 10:30:01 +1200 NZST
[server.foo.com-meta-2019-05-07.tar.gz] vs. [server.foo.com-meta-2019-05-07.tar.gz]
Remove those links that I added as a workaround (so, back to the environment that I discovered this bug):
root@server:/usr/share/zoneinfo# rm NZ{ST,DT}
Results are broken (all After
results do not correctly list NZST
from the metadata as +1200
):
root@server:/usr/share/zoneinfo# TZ=NZ ~/test.pl
Before: 1557181801 , 1 , 30 , 10 , 7 , 4 , 119 , 2 , 126 , 0 , 2019-05-07 10:30:01 +1200 NZST
After: 1557181801 , 1 , 30 , 22 , 6 , 4 , 119 , 1 , 125 , 0 , 2019-05-06 22:30:01 +0000 NZST
[server.foo.com-meta-2019-05-07.tar.gz] vs. [server.foo.com-meta-2019-05-06.tar.gz]
root@server:/usr/share/zoneinfo# TZ=NZST ~/test.pl
Before: 1557181801 , 1 , 30 , 22 , 6 , 4 , 119 , 1 , 125 , 0 , 2019-05-06 22:30:01 +0000 NZST
After: 1557181801 , 1 , 30 , 22 , 6 , 4 , 119 , 1 , 125 , 0 , 2019-05-06 22:30:01 +0000 NZST
[server.foo.com-meta-2019-05-07.tar.gz] vs. [server.foo.com-meta-2019-05-06.tar.gz]
root@server:/usr/share/zoneinfo# TZ=UTC ~/test.pl
Before: 1557181801 , 1 , 30 , 22 , 6 , 4 , 119 , 1 , 125 , 0 , 2019-05-06 22:30:01 +0000 UTC
After: 1557181801 , 1 , 30 , 22 , 6 , 4 , 119 , 1 , 125 , 0 , 2019-05-06 22:30:01 +0000 NZST
[server.foo.com-meta-2019-05-07.tar.gz] vs. [server.foo.com-meta-2019-05-06.tar.gz]
... I'll add, I'm not sure what the right answer is, but a start might be to store Olsen time zones in the meta file?
Edit: We use Pacific/Auckland
here, not NZST
or NZDT
. The abbreviations are outputs of time calculations to show when DST is active, but that's about it. For example:
root@server:/usr/share/zoneinfo# TZ=Pacific/Auckland date
Wed May 15 11:16:41 NZST 2019
root@server:/usr/share/zoneinfo# TZ=Pacific/Auckland date --date="3 months ago"
Fri Feb 15 12:16:50 NZDT 2019
Edit2: using the NZ
abbreviation also works, but it's deprecated.
Edit3: and just as another example:
root@server:/usr/share/zoneinfo# date
Tue May 14 23:19:33 UTC 2019
root@server:/usr/share/zoneinfo# TZ=CST date
Tue May 14 23:19:38 CST 2019
root@server:/usr/share/zoneinfo# TZ=CDT date
Tue May 14 23:19:41 CDT 2019
root@server:/usr/share/zoneinfo# TZ=America/Chicago date
Tue May 14 18:19:58 CDT 2019
root@server:/usr/share/zoneinfo# TZ=America/Chicago date --date="3 months ago"
Thu Feb 14 17:20:14 CST 2019
OK. Can I ask you to:
- provide me with information about os (distro, version)
- perl version and details (perl -V output)
- do: export TZ=NZST; strace -ff -o for.depesz.log -s 256 -tt -T perl test.pl
- the strace command will generate couple (maybe just one) file. compress them and attach to this issue.
this will generate
with or without the links in place in /usr/share/zoneinfo
?
with. Without it will definitely not work, but with links in place, it should work, so let's see why it doesn't.
I'm very confused - with the links in place, it does work. Note that the test situation I'm showing you is where the backup was made on a host with the Pacific/Auckland
(currently NZST
) timezone, and cleanup was running on a host set to Etc/UTC
. The timestamp is 07/05/19 in NZST (same as the meta filename), and 06/05/19 in UTC (which is what perl is calculating without the links in place - like it's the same as the local system time - UTC).
I can't really tell what's happening, but it looks that for whatever reason perl wasn't able to read the tz description on the backup host, when it was trying to do the cleanup.
Not sure what could be solution in here, other than using UTC everywhere.
I'm not sure I can be more clear about what's happening. Perl is doing exactly the same as /bin/date
in my testing above. It's trying to use the output of strftime('%Z', localtime);
which is saved to the meta file, as a timezone to regenerate the date that the backup was made, to verify the meta filename.
The short form timezone output from %Z
is NOT a valid value to use for $ENV{TZ}
.
OK, then this leads to question: how do I get proper value for TZ?
Just check ENV["TZ"]? What if it's not set?
There is POSIX::tzname, but it returns two names - one for standard, and one for daylight savings time.
Currently, the only sane solution I can see is to use gmtime() for filename generation, but it will have the side effect that names will not match what you see by calling "date".
Any opinion on what you'd like to happen?
Use Olson zones: https://metacpan.org/pod/Time::Zone::Olson
Hi, so I,ve read some on the Olson module, and generated this test script: https://gist.github.com/depesz/c7e11c0e8d731533ef25b5f6f851e474
Can you please run it in your environment, and let me know if it works OK?
it's been a month, i assume the problem is no longer important/valid.
No, it's still important, I just haven't gotten around to testing your script - The system doesn't have Time::Zone::Olson
available as a package, and I hadn't had time to install from cpan.
Instead of using Date::Time::Olson
, I tweaked your script to just use DateTime
which uses Olson timezones as well. Here's the script:
#!/usr/bin/env perl
use strict;
use POSIX qw( strftime );
use DateTime;
sub strftime_at_timezone_olson {
my ( $format, $time, $timezone ) = @_;
my $dt = DateTime->from_epoch( epoch => $time );
$dt->set_time_zone( $timezone );
return $dt->strftime( $format );
}
my $meta = {
'started-epoch' => '1557181801',
'timezone' => 'NZST',
'hostname' => 'server.foo.com',
'min-xlog' => '0000000100000000000000CC',
'file_name' => 'server.foo.com-meta-2019-05-07.tar.gz'
};
my $filename_mask = 'server.foo.com-meta-%Y-%m-%d.tar.gz';
my $meta_filename_verification = strftime_at_timezone_olson( $filename_mask, $meta->{ 'started-epoch' }, $meta->{ 'timezone' } );
printf "[%s] vs. [%s]\n", $meta->{ 'file_name' }, $meta_filename_verification;
exit;
And the Output:
$meta->timezone
set to NZST
:
root@server:~# ./olson.pl
Invalid offset: NZST
$meta->timezone
set to Pacific/Auckland
:
root@server:~# ./olson.pl
[server.foo.com-meta-2019-05-07.tar.gz] vs. [server.foo.com-meta-2019-05-07.tar.gz]
$meta->timezone
set to Etc/UTC
:
root@server:~# ./olson.pl
[server.foo.com-meta-2019-05-07.tar.gz] vs. [server.foo.com-meta-2019-05-06.tar.gz]
Well, given that DateTime can't parse NZST it is of no big use.
I just committed b5e3352 that solves the problem another way.
It makes all future meta files contain time zone as offset, and as such it will be parseable, and usable by normal POSIX::tzset().
I tested it myself, and it looks that after this change cleanup works correctly.
Of course - you will need to manually change meta files that were generated previously, but that shouldn't be big work.
Please check if it solves your case, and let me know, so I can release new version.
Well, given that DateTime can't parse NZST it is of no big use.
That's the point. NZST
is not a valid timezone. The correct thing to do is to store the Olson timezone in the meta files, not the output of strftime('%Z', localtime);
, which doesn't provide a valid timezone. Storing offset is the next best thing, so I'll test your code in the next week or so and let you know.