# TZ variable

## ippipp

Hi!

I found this post and tested it on my laptop: https://blog.packagecloud.io/eng/2017/02/21/set-environment-variable-save-thousands-of-system-calls/

I compared  "./test" and "TZ=:/etc/localtime strace -ttT ./test"  and this gave me similar results as in that blog post.

Questions:

1) Is it safe to use this variable in gentoo globally?

and

2) What is best way to set it system wide?

----------

## NeddySeagoon

ippipp,

Maybe.  On Gentoo, /etc/localtime should be a file.  With some use cases, a symlink is a very bad thing.

One of the OpenRC startup services uses    /etc/timezone to make a new copy of the timezone file every boot.

This means that your timezone file in use, is only updated every boot regardless of what emerge installs.

Setting TZ will change nothing there.

With a  /etc/localtime symlink, the timezone file will change as soon as emerge updates /usr/share/zoneinfo/ (if your timezone happens to change)

With TZ set, you would not get the change until you updated TZ.

Its only going to catch you out if you rarely reboot or go a long time between updates and your timezone file in use gets changed.

Its always safe for UTC as that never changes.

TZ should be set by whatever service does the /etc/localtime copy, so that if you restart it, TZ gets updated too.

----------

## cboldt

Neddy:

TZ is just an environment variable that points to /etc/localtime.  /etc/localtime remains a regular file.  If /etc/localtime changes, TZ still points to the same (now changed) file.

Not to say there aren't any hidden issues, there may be.  But the way I read your concern, it (your concern) doesn't come into play.

ippipp: Set environment variables from files in /etc/env.d  ...  I use /etc/env.d/00Local for any environment variables not assigned to a /etc/env.d file by package installation.  After you make a change anywhere in /etc/env.d, you have to run `env-update` to cause those changes to be consolidated into /etc/profile.env (which, for bash, is read/sourced by /etc/profile) and into /etc/csh.env

Bear in mind that those changes aren't automatically picked up by any running shell.

----------

## NeddySeagoon

cboldt,

/etc/localtime is only changed by a service startup script.

As a regular file it can be out of date with the file in /usr/share/zoneinfo/ until the service is restarted.

Its certainly a corner case. 

On a desktop that's rebooted every day, or even every six weeks to keep the kernel current, its a non issue.

----------

## cboldt

Neddy:

/usr/share/zoneinfo/ only changes when sys-libs/timezone-data is updated.  As you point out, this can be more frequent than rebooting.  My recent history of updating timezone-data:

```
     Sat Aug 15 04:20:38 2015 >>> sys-libs/timezone-data-2015e

     Sat Oct  3 03:28:28 2015 >>> sys-libs/timezone-data-2015f

     Sat Feb  6 04:37:00 2016 >>> sys-libs/timezone-data-2015g

     Sat Apr  9 05:01:00 2016 >>> sys-libs/timezone-data-2016a

     Sat May 14 05:03:43 2016 >>> sys-libs/timezone-data-2016c

     Sat Jun 25 05:26:54 2016 >>> sys-libs/timezone-data-2016d

     Sat Aug  6 04:57:51 2016 >>> sys-libs/timezone-data-2016e

     Sat Nov 12 04:51:31 2016 >>> sys-libs/timezone-data-2016h
```

I see the corner cases as those where the date for entering and exiting daylight saving time moves around.

Out of curiosity, what service writes /etc/localtime?  My etc/localtime has pretty near the same date as the last time timezone-data was emerged.  This is the case on all (three) the machines involved in my review, and I know all three of them have been rebooted between November last year and now.

----------

## khayyam

 *cboldt wrote:*   

> Out of curiosity, what service writes /etc/localtime?  My etc/localtime has pretty near the same date as the last time timezone-data was emerged.  This is the case on all (three) the machines involved in my review, and I know all three of them have been rebooted between November last year and now.

 

cboldt ... that would be because it's done in pkg_config() and not via a service:

```
% less +119 $(portageq get_repo_path / gentoo)/sys-libs/timezone-data/timezone-data-2016h.ebuild
```

best ... khay

----------

## cboldt

khayyam:

Thanks for that.  LOL at ...

```
else

     tz="FOOKABLOIE"

```

For what it's worth, TZ="" on the systems here.  Not defined at all.  I gather from reading the URL's in the ebuild, and the elog message under pkg_preinst, that a common practice is to define TZ to be the name of a file under /usr/share/zoneinfo, for example, TZ=EST5EDT

----------

## John R. Graham

Long ago (ca. 8 years ago) it was a symlink. However, some systems don't have /usr mounted before the very first usage of the time zone info, so it was made into a copy.

- John

----------

## NeddySeagoon

khayyam,

Thank you.

I'm sure it used to be a service but I remember /etc/localtime being a symlink too and having a separate /usr, so the symlink was broken until /usr was mounted.

----------

## khayyam

 *cboldt wrote:*   

> For what it's worth, TZ="" on the systems here.  Not defined at all.  I gather from reading the URL's in the ebuild, and the elog message under pkg_preinst, that a common practice is to define TZ to be the name of a file under /usr/share/zoneinfo, for example, TZ=EST5EDT

 

cboldt ... yes, or TZ=<continent>/<city> (or, similar). I'd always assumed this would be defined in the env, but I see it's only hwclock that seems to use /etc/localtime, and that its not.

best ... khay

----------

## cboldt

Researching a little, for education, I was pointed to `man 3 tzset`

Seems the system will seek info first from $TZ, then from /etc/localtime

The only reference to plaintext "EST5EDT" on the configuration part of my system is in /etc/timezone.  Nothing in the /etc branch includes the string "timezone," which cause me to conclude that /etc/timezone is used by the ebuild you cited, to copy the correct file from /usr/share/zoneinfo, into /etc/localtime.  And by golly, looking at timezone-data-2016h.ebuild, there it is, in the get_TIMEZONE routine.

At this point, I am still not sure of the better/best setting for the TZ variable.  And to make the point more precisely, that variable does not exist in my environment - which is different from it exists but is empty, which is what I implied before.

----------

## khayyam

 *cboldt wrote:*   

> At this point, I am still not sure of the better/best setting for the TZ variable.  And to make the point more precisely, that variable does not exist in my environment - which is different from it exists but is empty, which is what I implied before.

 

cboldt ... you can do as the above linked article suggests and set it to ':/etc/localtime', or ':EST5EDT' ...

```
The second format specifies that the timezone information should be read from a file:

  :[filespec]

If the file specification filespec is omitted, or its value cannot be interpreted, then Coordinated Universal Time (UTC) is used. If filespec is given, it specifies another tzfile(5)-format file to read the timezone information from. If filespec does not begin with a '/', the file specification is relative to the system timezone directory. If the colon is omitted each of the above TZ formats will be tried.

Here's an example, once more for New Zealand:

  TZ=":Pacific/Auckland"
```

HTH & best ... khay

----------

## cboldt

Now I wonder if there is a way to get the string so there is no need to open the file, if TZ is defined.

```
The first format is a string of characters that directly represent the timezone to be used:

              std offset[dst[offset][,start[/time],end[/time]]] ...

TZ="NZST-12:00:00NZDT-13:00:00,M10.1.0,M3.3.0"
```

I know I can figure that out "manually," but it appears to be the information stored in the zoneinfo file.  I wonder if there is a sort of a "reverse zic", except the output would be in the TZ variable format that tzset describes.

Also for what it's worth, running `tzselect`, I am told to use TZ='America/New_York'

No colon in there, just the filename relative to /usr/share/zoneinfo/

----------

## khayyam

 *cboldt wrote:*   

> Now I wonder if there is a way to get the string so there is no need to open the file, if TZ is defined. [...] I know I can figure that out "manually," but it appears to be the information stored in the zoneinfo file.  I wonder if there is a sort of a "reverse zic", except the output would be in the TZ variable format that tzset describes.

 

cboldt ... that might be more effort than it's worth, by setting ':/etc/localtime' (and with /etc/timezone set correctly) then you will get that exact same definition, and it will be updated (should it happen to change).

 *cboldt wrote:*   

> Also for what it's worth, running `tzselect`, I am told to use TZ='America/New_York'. No colon in there, just the filename relative to /usr/share/zoneinfo/

 

Yes, because there two 'formats', ':[filespec]' being the second.

best ... khay

----------

## cboldt

The variable string is pretty easy to figure out, and even if it changes, I suspect I'd get plenty of notice.

TZ="EST+5EDT,M3.2.0/2,M11.1.0/2"

Go into daylight saving the second Sunday in March at 2 am   (M3.2.0/2) - "0" being "Sunday"

Go into standard time the first Sunday in November at 2 am    (M11.1.0/2)

EST is +5 hours from GMT.

I don't care about any imprecision on the diff between GMT and UTC, leap seconds and other esoterica.

I expect my user experience at the console to change from "just okay" to "ZOOOMomyGod!" with this improvement.

----------

## khayyam

 *cboldt wrote:*   

> I expect my user experience at the console to change from "just okay" to "ZOOOMomyGod!" with this improvement.

 

cboldt ... hehe ... yup, welcome to the land of go-faster stripes ;)

best ... khay

----------

## mv

 *NeddySeagoon wrote:*   

> With some use cases, a symlink is a very bad thing.

 

Why? I have it a symlink since ages and never had any problems with it.

The advantage of having it a symlink is that I can always see (and easily check by scripts) in which timezone my system actually is currently configured.

 *Quote:*   

> One of the OpenRC startup services uses    /etc/timezone to make a new copy of the timezone file every boot.

 

Are you sure it is openrc? I have no records that I changed this locally (but maybe my records are faulty in this point):

The sys-libs/timezone ebuild used to change this - I remember that for some years I had a local patch because of this. Fortunately, this has changed long ago.

----------

## mv

 *cboldt wrote:*   

> I expect my user experience at the console to change from "just okay" to "ZOOOMomyGod!" with this improvement.

 

If the numbers in the article are correct, it could make an improvement of 0.1-1 percent when the system is under heavy load. If I (as being a user of the symlink) can get this improvement when encoding a video or emerging a huge program without any cost, I willl do it.

As a practical hint: You should probably also modify /etc/sudoers and /etc/rc.conf to pass the TZ variable instead of clearing it, since otherwise it might not get through to the daemons which actually consume it.

I hope that the localtime() glibc function is written well enough that it has no leak if it gets passed a corrupted file...

But the main question actually is: Which damn stupid daemon author thinks that it is a great idea to call localtime() some thousand times a second?

I make a guess: The same people who think it is a great idea to have a javascript interpreter running in a daemon which can access root permissions?

My guess is that if you remove that gapping security holes from your system you have the same effect and even much more...

----------

## cboldt

My /etc/sudoers and /etc/rc.conf make no mention of TZ.  In all of /etc here, the only mentions of TZ are in /etc/localtime (a copy of the EST5EDT file, graciously installed by the timezone-data package), /etc/exim/exim.conf.dist (which merely informs me that exim handles TZ separately, whatever that means), and also commented out as one of the forms of ENV_TZ in /etc/login.defs, with the other form being "ENV_TZ   /etc/tzname", also effective only if uncommented.

Good point about the propagation of TZ.  If set in the environment, it only goes where bash/csh does.

----------

## cboldt

Oh, the issue with the symlink is that "/usr on a separate partition" thing.

----------

## mv

 *cboldt wrote:*   

> My /etc/sudoers and /etc/rc.conf make no mention of TZ.

 

Of course not. That's why I suggested to include it: By default, all variables which you do not explicitly allow in these two files are filtered by sudo and openrc for security reasons. In particular, none of the daemons will have TZ in their environment, and this is what you mainly want to profit from the idea.

Note that allowing these variables for sudo (and parhaps also for openrc) might be a security risk, because a (non-root) user might pass a specially prepared file in this way to a privileged program. That's why I wrote that I hope that glibc has no bug in localtime() and cannot be corrupted  this way.

----------

## cboldt

Ahhh, I mistook your "instead of clearing it [the TZ variable]" as sudo taking some affirmative action against that specific variable.  cron also doesn't pass the environment, more on that below.

Good tip that openrc-run picks up the setting of "random" environment variables in rc.conf.  The man page says as much, but with no example, I would not have thought to use that.

```
When a service runs a command it first loads its multiplexed configuration file, then its master configuration file, then /etc/rc.conf and finally the script itself.
```

I tried that by putting "CRONVAR=woohoo"  into /etc/rc.conf, restarting vixie-cron, and adding a temporary cron job `env`.  vixie-cron resisted my attempt to augment the environment in that fashion.  Not to say no service will pick up that variable, only that vixie-cron does not.  My conclusion is that if it matters to a person that TZ=(whatever) gets passed to a service, to study that service.

----------

## steveL

 *ippipp wrote:*   

> I found this post and tested it on my laptop: https://blog.packagecloud.io/eng/2017/02/21/set-environment-variable-save-thousands-of-system-calls/
> 
> I compared  "./test" and "TZ=:/etc/localtime strace -ttT ./test"  and this gave me similar results as in that blog post.

 

That's remarkable; simply setting the same filename, results in such an improvement.

 *Quote:*   

> 1) Is it safe to use this variable in gentoo globally?

 

What Neddy said, which I'd sum up as: yes, if you're on a desktop or laptop, or your server is using UTC.

 *Quote:*   

> 2) What is best way to set it system wide?

 

/etc/env.d would be best; that'll also go through to the openrc environment for initscripts.

Not sure if it isn't a bug in glibc though. I'd have to check the POSIX documentation, but it wouldn't surprise me if timezone was meant to be process-lifetime.

----------

## Mr. T.

I have musl as system library and I set the TZ environment variable in /etc/environment. I have installed timezone-data for the sake of convenience and 

set TZ to "Europe/Paris" but "NFT-1DST,M3.5.0,M10.5.0" works too.

----------

## R0b0t1

At this point I've seen a number of these relatively undocumented tricks. Is there a list of common and not-so-common optimizations anywhere? The Wiki, perhaps?

----------

## Mr. T.

 *R0b0t1 wrote:*   

> At this point I've seen a number of these relatively undocumented tricks. Is there a list of common and not-so-common optimizations anywhere? The Wiki, perhaps?

 

It is not an optimization in itself, but a feature of the system.

----------

## Leio

It also breaks things like automatic timezone updates from geolocation and so on. So you need to know what you're doing if applying such "optimization". But yes, it can be useful on a server that is agreed to always be a certain timezone, on laptop/desktop - not so much as its workflows don't really hit that like some specific cases for a server software where I also read about this.

----------

## Ant P.

Just to make sure - does musl copy glibc's dumb behaviour here?

----------

