108.1 Lesson 1
Certificate: |
LPIC-1 (102) |
---|---|
Version: |
5.0 |
Topic: |
108 Essential System Services |
Objective: |
108.1 Maintain system time |
Lesson: |
1 of 2 |
Introduction
Accurate timekeeping is absolutely crucial for modern computing. The implementation of keeping time, however, is surprisingly complex. The practice of keeping time seems trivial to an end-user, but the system needs to be able to handle many idiosyncrasies and edge cases intelligently. Consider that time zones are not static, but may be changed by an administrative or political decision. A country may choose to stop observing Daylight Savings Time. Any program must be able to handle those changes logically. Fortunately for system administrators, the solutions for timekeeping on the Linux operating system are mature, robust and usually work without much interference.
When a Linux computer boots up, it starts keeping time. We refer to this as a system clock, since it is updated by the operating system. In addition, modern computers will also have a hardware or real time clock. This hardware clock is often a feature of the motherboard and keeps time regardless if the computer is running or not. During boot, the system time is set from the hardware clock, but for the most part these two clocks run independently of each other. In this lesson we will be discussing methods of interacting with both the system and hardware clocks.
On most modern Linux systems, system time and hardware time are synchronised to network time, which is implemented by the Network Time Protocol (NTP). In the vast majority of cases, the only configuration a normal user will be required to do is to set their time zone and NTP will take care of the rest. However, we will cover some ways of working with time manually and the specifics of configuring network time will be covered in the next lesson.
Local Versus Universal Time
The system clock is set to Coordinated Universal Time (UTC), which is the local time at Greenwich, United Kingdom. Usually a user wants to know their local time. Local time is calculated by taking UTC time and applying an offset based on time zone and Daylight Savings. In this way, a lot of complexity can be avoided.
The system clock can be set to either UTC time or local time, but it is recommended that it also be set to UTC time.
Date
date
is a core utility which simply prints local time:
$ date Sun Nov 17 12:55:06 EST 2019
Modifying the options of the date
command will change the format of the output.
For example, a user can use date -u
to view the current UTC time.
$ date -u Sun Nov 17 18:02:51 UTC 2019
Some other commonly-used options will return the local time in a format which adheres to an accepted RFC format:
-I
-
Date/time in ISO 8601 format. Appending
date
(-Idate
) will limit the output to date only. Other formats arehours
,minutes
,seconds
andns
for nanoseconds. -R
-
Returns date and time in RFC 5322 format.
--rfc-3339
-
Returns date and time in RFC 3339 format.
The format of date
can be customized by the user with sequences specified in the man page. For example, the current time can be formatted as Unix time thusly:
$ date +%s 1574014515
From date
's man page we can see that %s
refers to Unix time.
Unix time is used internally on most Unix-like systems. It stores UTC time as the number of seconds since Epoch, which has been defined as January 1st, 1970.
Note
|
The number of bits required to store Unix time at the present moment is 32 bits. There is a future issue when 32 bits will become insufficient to contain the current time in Unix format. This will cause serious issues for any 32-bit Linux systems. Fortunately, this will not occur until January 19, 2038. |
Using these sequences, we are able to format date and time in almost any format required by any application. Of course, in most cases it is far preferable to stick with an accepted standard.
Additionally, date --date
can be used to format a time that is not the current time. In this scenario, a user can specify the date to be applied to the system using Unix time for example:
$ date --date='@1564013011' Wed Jul 24 20:03:31 EDT 2019
Using the --debug
option can be very useful for ensuring that a date can be successfully parsed. Observe what happens when passing a valid date to the command:
$ date --debug --date="Fri, 03 Jan 2020 14:00:17 -0500" date: parsed day part: Fri (day ordinal=0 number=5) date: parsed date part: (Y-M-D) 2020-01-03 date: parsed time part: 14:00:17 UTC-05 date: input timezone: parsed date/time string (-05) date: using specified time as starting value: '14:00:17' date: warning: day (Fri) ignored when explicit dates are given date: starting date/time: '(Y-M-D) 2020-01-03 14:00:17 TZ=-05' date: '(Y-M-D) 2020-01-03 14:00:17 TZ=-05' = 1578078017 epoch-seconds date: timezone: system default date: final: 1578078017.000000000 (epoch-seconds) date: final: (Y-M-D) 2020-01-03 19:00:17 (UTC) date: final: (Y-M-D) 2020-01-03 14:00:17 (UTC-05)
This can be a handy tool when troubleshooting an application that generates a date.
Hardware Clock
A user may run the hwclock
command to view the time as maintained on the real-time clock. This command will require elevated privileges, so we will use sudo
to call the command in this case:
$ sudo hwclock 2019-11-20 11:31:29.217627-05:00
Using the option --verbose
will return more output which might be useful for troubleshooting:
$ sudo hwclock --verbose hwclock from util-linux 2.34 System Time: 1578079387.976029 Trying to open: /dev/rtc0 Using the rtc interface to the clock. Assuming hardware clock is kept in UTC time. Waiting for clock tick... ...got clock tick Time read from Hardware Clock: 2020/01/03 19:23:08 Hw clock time : 2020/01/03 19:23:08 = 1578079388 seconds since 1969 Time since last adjustment is 1578079388 seconds Calculated Hardware Clock drift is 0.000000 seconds 2020-01-03 14:23:07.948436-05:00
Note the Calculated Hardware Clock drift
. This output can tell you if system time and hardware time are deviating from one another.
timedatectl
timedatectl
is a command that can be used to check the general status of time and date, including whether or not network time has been synchronised (Network Time Protocol will be covered in the next lesson).
By default timedatectl
returns information similar to date
, but with the addition of the RTC (hardware) time as well as the status of the NTP service:
$ timedatectl Local time: Thu 2019-12-05 11:08:05 EST Universal time: Thu 2019-12-05 16:08:05 UTC RTC time: Thu 2019-12-05 16:08:05 Time zone: America/Toronto (EST, -0500) System clock synchronized: yes NTP service: active RTC in local TZ: no
Setting Time Using timedatectl
If NTP is unavailable, it is recommended to use timedatectl
rather than date
or hwclock
to set time:
# timedatectl set-time '2011-11-25 14:00:00'
The process is similar to that of date
. The user can also set time independent of date using the format HH:MM:SS.
Setting Timezone Using timedatectl
timedatectl
is the preferred way of setting the local time zone on systemd
based Linux systems when no GUI exists. timedatectl
will list possible time zones and then the time zone can be set using one of these as an argument.
First we will list possible timezones:
$ timedatectl list-timezones Africa/Abidjan Africa/Accra Africa/Algiers Africa/Bissau Africa/Cairo ...
The list of possible time zones is long, so the use of the grep
command is recommended in this case.
Next we can set the timezone using one of the elements of the list that was returned:
$ timedatectl set-timezone Africa/Cairo $ timedatectl Local time: Thu 2019-12-05 18:18:10 EET Universal time: Thu 2019-12-05 16:18:10 UTC RTC time: Thu 2019-12-05 16:18:10 Time zone: Africa/Cairo (EET, +0200) System clock synchronized: yes NTP service: active RTC in local TZ: no
Keep in mind that the name of the time zone must be exact. Africa/Cairo
for example will change the time zone, but cairo
or africa/cairo
will not.
Disabling NTP Using timedatectl
In some cases it might be necessary to disable NTP. This could be done using systemctl
but we will demonstrate this using timedatectl
:
# timedatectl set-ntp no $ timedatectl Local time: Thu 2019-12-05 18:19:04 EET Universal time: Thu 2019-12-05 16:19:04 UTC RTC time: Thu 2019-12-05 16:19:04 Time zone: Africa/Cairo (EET, +0200) NTP enabled: no NTP synchronized: no RTC in local TZ: no DST active: n/a
Setting Time Zone Without timedatectl
Setting time zone information is a standard step when installing Linux on a new machine. If there is a graphical installation process, this will most likely be handled without any further user input.
The /usr/share/zoneinfo
directory contains information for the different time zones that are possible. In the zoneinfo
directory, there are subdirectories that contain the names of continents as well as other symbolic links. It is recommended to find your region’s zoneinfo
starting from your continent.
zoneinfo
files contain rules required to calculate the local time offset in relation to UTC, and they also are important if your region observes Daylight Savings Time. The contents of /etc/localtime
will be read when Linux needs to determine the local time zone. In order to set the time zone without the use of a GUI, the user should create a symbolic link for their location from /usr/share/zoneinfo
to /etc/localtime
. For example:
$ ln -s /usr/share/zoneinfo/Canada/Eastern /etc/localtime
After setting the correct time zone, it is often recommended to run:
# hwclock --systohc
This will set the hardware clock from the system clock (that is, the real-time clock will be set to the same time as date
). Please note that this command is run with root privileges, in this case by being logged in as root.
/etc/timezone
is similar to /etc/localtime
. It is a data representation of the local time zone, and as such it can be read using cat
:
$ cat /etc/timezone America/Toronto
Note that this file is not used by all Linux distributions.
Setting Date and Time Without timedatectl
Note
|
Most modern Linux systems use |
Using date
date
has an option to set the system time. Use --set
or -s
to set the date and time. You may also choose to use --debug
to verify the correct parsing of the command:
# date --set="11 Nov 2011 11:11:11"
Note that root privileges are required to set the date here. We may also choose to change to time or date independently:
# date +%Y%m%d -s "20111125"
Here we must specify the sequences so that our string is parsed properly. For example %Y
refers to the year, and so the first four digits 2011
will be interpreted as the year 2011. Similarly, %T
is the sequence for time, and it is demonstrated here by setting time:
# date +%T -s "13:11:00"
After changing system time, it is recommended to also set the hardware clock so that both system and hardware clocks are synchronised:
# hwclock --systohc
systohc
means “system clock to hardware clock”.
Using hwclock
Rather than setting the system clock and updating the hardware clock, you may choose to reverse the process. We will start by setting the hardware clock:
# hwclock --set --date "4/12/2019 11:15:19" # hwclock Fri 12 Apr 2019 6:15:19 AM EST -0.562862 seconds
Notice that by default hwclock
is expecting UTC time, but returns the local time by default.
After setting the hardware clock, we will need to update the system clock from it. hctosys
can be understood to mean “hardware clock to system clock”.
# hwclock --hctosys
Guided Exercise
-
Indicate whether the following commands are displaying or modifying system time or hardware time:
Command(s) System Hardware Both date -u
hwclock --set --date "12:00:00"
timedatectl
timedatectl | grep RTC
hwclock --hctosys
date +%T -s "08:00:00"
timedatectl set-time 1980-01-10
-
Observe the following output, and then correct the format of the argument so that the command is successful:
$ date --debug --date "20/20/12 0:10 -3" date: warning: value 20 has less than 4 digits. Assuming MM/DD/YY[YY] date: parsed date part: (Y-M-D) 0002-20-20 date: parsed time part: 00:10:00 UTC-03 date: input timezone: parsed date/time string (-03) date: using specified time as starting value: '00:10:00' date: error: invalid date/time value: date: user provided time: '(Y-M-D) 0002-20-20 00:10:00 TZ=-03' date: normalized time: '(Y-M-D) 0003-08-20 00:10:00 TZ=-03' date: ---- -- date: possible reasons: date: numeric values overflow; date: incorrect timezone date: invalid date ‘20/20/2 0:10 -3’
-
Use the
date
command and sequences so that the system’s month is set to February. Leave the rest of the date and time unchanged. -
Assuming that the command above was successful, use
hwclock
to set the hardware clock from the system clock. -
There is a location called
eucla
. What continent is it part of? Use thegrep
command to find out. -
Set your current timezone to that of
eucla
.
Explorational Exercises
-
Which method of setting time is optimal? In what scenario might the preferred method be impossible?
-
Why do you think there are so many methods to accomplish the same thing, i.e. setting system time?
-
After January 19, 2038, Linux System Time will require a 64-bit number to store. However, it is possible that we could simply choose to set a “New Epoch”. For example, January 1st, 2038 at midnight could be set to a New Epoch Time of
0
. Why do you think this has not become the preferred solution?
Summary
In this lesson you learned:
-
How to display the time in different formats from the command line.
-
The difference between the system clock and the hardware clock in Linux.
-
How to manually set the system clock.
-
How to manually set the hardware clock.
-
How to change the system’s time zone.
Commands used in this lesson:
date
-
Display or the change the system clock. Other options:
-u
-
Display UTC time.
+%s
-
Use a sequence to display Epoch time.
--date=
-
Specify a specific time to display, as opposed to current time.
--debug
-
Display debug messages when parsing a user-inputted date.
-s
-
Set system clock manually.
hwclock
-
Display or change the hardware clock.
--systohc
-
Use system clock to set hardware clock.
--hctosys
-
Use hardware clock to set system clock.
--set --date
-
Set hardware clock manually.
timedatectl
-
Display system and hardware clocks, as well as NTP configuration on systemd-based Linux systems.
set-time
-
Set the time manually.
list-timezones
-
List possible timezones.
set-timezone
-
Set timzone manually.
set-ntp
-
Enable/disable NTP.
Answers to Guided Exercises
-
Indicate whether the following commands are displaying or modifying system time or hardware time:
Command(s) System Hardware Both date -u
X
hwclock --set --date "12:00:00"
X
timedatectl
X
timedatectl | grep RTC
X
hwclock --hctosys
X
date +%T -s "08:00:00"
X
timedatectl set-time 1980-01-10
X
-
Observe the following output, and then correct the format of the argument so that the command is successful:
$ date --debug --date "20/20/12 0:10 -3" date: warning: value 20 has less than 4 digits. Assuming MM/DD/YY[YY] date: parsed date part: (Y-M-D) 0002-20-20 date: parsed time part: 00:10:00 UTC-03 date: input timezone: parsed date/time string (-03) date: using specified time as starting value: '00:10:00' date: error: invalid date/time value: date: user provided time: '(Y-M-D) 0002-20-20 00:10:00 TZ=-03' date: normalized time: '(Y-M-D) 0003-08-20 00:10:00 TZ=-03' date: ---- -- date: possible reasons: date: numeric values overflow; date: incorrect timezone date: invalid date ‘20/20/2 0:10 -3’
date --debug --set "12/20/20 0:10 -3"
-
Use the
date
command and sequences so that the system’s month is set to February. Leave the rest of the date and time unchanged.date +%m -s "2"
-
Assuming that the command above was successful, use
hwclock
to set the hardware clock from the system clock.hwclock -systohc
-
There is a location called
eucla
. What continent is it part of? Use thegrep
command to find out. Enter the complete command below:timedatectl list-timezones \| grep -i eucla
OR
grep -ri eucla /usr/share/zoneinfo
-
Set your current timezone to that of
eucla
.timedatectl set-timezone 'Australia/Eucla'
or
ln -s /usr/share/zoneinfo/Australia/Eucla /etc/localtime
Answers to Explorational Exercises
-
Which method of setting time is optimal? In what scenario might the preferred method be impossible?
In most Linux distributions, NTP is enabled by default and should be left to set system time without interference. However, if there is a Linux system that isn’t connected to the internet, NTP will be inaccessible. For example, an embedded Linux system running on industrial equipment might not have network connectivity.
-
Why do you think there are so many methods to accomplish the same thing, i.e. setting system time?
Since setting time has been a requirement of all *nix systems for decades, there are many legacy methods for setting time that are still maintained.
-
After January 19, 2038, Linux System Time will require a 64-bit number to store. However, it is possible that we could simply choose to set a “New Epoch”. For example, January 1st, 2038 at midnight could be set to a New Epoch Time of
0
. Why do you think this has not become the preferred solution?By 2038 the vast majority of computers will already be running 64-bit CPUs, and using a 64-bit number won’t degrade performance in any significant way. However, it would be impossible to estimate the risks of “resetting” Epoch time in such a way. There is a lot of legacy software that might be impacted. Banks and large businesses, for example, often have a large amount of older programs that they rely on for internal use. So this scenario, like so many others, is a study in trade-offs. Any 32-bit systems still running in 2038 would be impacted by an Epoch Time overflow, but legacy software would be impacted by changing the value of Epoch.