Manage System Time and Schedule Tasks on Oracle Linux
Introduction
Oracle Linux provides users with several ways to interact with the time and date. While you can change these manually, it is more common to configure a service that implements the Network Time Protocol (NTP), such as chrony . This way, your system time remains correct, and any tasks using cron
or systemd timers
run on schedule.
Objectives
In this tutorial, you'll learn to:
- Manage your system time from the terminal using
date
,hwclock
, andtimedatectl
- Run and enable the chrony service
- Schedule tasks with cron and systemd timers
Prerequisites
Minimum of a single Oracle Linux system
Each system should have Oracle Linux installed and configured with:
- A non-root user account with sudo access
- Access to the Internet
Deploy Oracle Linux
Note: If running in your own tenancy, read the linux-virt-labs
GitHub project README.md and complete the prerequisites before deploying the lab environment.
Open a terminal on the Luna Desktop.
Clone the
linux-virt-labs
GitHub project.git clone https://github.com/oracle-devrel/linux-virt-labs.git
Change into the working directory.
cd linux-virt-labs/ol
Install the required collections.
ansible-galaxy collection install -r requirements.yml
Deploy the lab environment.
ansible-playbook create_instance.yml -e localhost_python_interpreter="/usr/bin/python3.6"
The free lab environment requires the extra variable
local_python_interpreter
, which setsansible_python_interpreter
for plays running on localhost. This variable is needed because the environment installs the RPM package for the Oracle Cloud Infrastructure SDK for Python, located under the python3.6 modules.The default deployment shape uses the AMD CPU and Oracle Linux 8. To use an Intel CPU or Oracle Linux 9, add
-e instance_shape="VM.Standard3.Flex"
or-e os_version="9"
to the deployment command.Important: Wait for the playbook to run successfully and reach the pause task. At this stage of the playbook, the installation of Oracle Linux is complete, and the instances are ready. Take note of the previous play, which prints the public and private IP addresses of the nodes it deploys and any other deployment information needed while running the lab.
Configure System Date and Time
Oracle Linux has three common commands that can help you adjust the date and time on your system. The date
command adjusts the system time, while hwclock
adjusts the RTC time. In Oracle Linux, the RTC time refers to the time kept by the Real-Time Clock (RTC), a battery-backed hardware clock that continues to run when the system is powered off. Other common names for the hardware clock include the CMOS clock or BIOS clock. If you want to update the RTC clock after a date
change, you must run hwclock
.
The third option is timedatectl
. This command combines date
and hwclock
and updates both the system and the RTC when setting the time. On modern systemd-based Linux distros such as Oracle Linux, the recommendation is to use timedatectl
.
Display and Set the System Clock
Open a terminal and connect via SSH to the ol-node-01 instance.
ssh oracle@<ip_address_of_instance>
Get the current system time and date.
date
The output shows the system's date, time, and timezone in the default format. You can change the output's format using the
date
command's many arguments. These arguments help when scripting or calculating different dates and times. Find more information by runningdate --help
or view the manual page usingman date
.Adjust the system time and date.
sudo date -s "1 JAN 1970 16:00:00"
Simplify the format by using the format control arguments.
sudo date +%Y%m%d -s "20250203"
Notice that since you did not provide a time, the time portion defaults to all zeros, which is midnight.
Set the system time.
sudo date +%T -s "14:08:14"
If you run the
date
command again, the time should display according to what you entered.
Display and Set the Hardware Clock
Read the current hardware clock (RTC).
sudo hwclock --show
Set the system clock based on the hardware clock.
sudo hwclock -s
The command lets you set the clocks in the opposite direction by passing the
-w
function. Check out additional functions and options by runninghwclock --help
or viewing the manual pageman hwclock
.
Date and Time Using Systemd
Get the current date and time.
timedatectl
The output in the free lab environment shows that the NTP service is active. To manually adjust the date and time settings with
timedatectl
, this must be disabled first.Disable the NTP synchronization.
sudo timedatectl set-ntp no
Set the date and time.
sudo timedatectl set-time '2014-09-23 14:10:40'
Check the date and time.
date
Get a list of time zones.
timedatectl list-timezones
Press
q
to exit thetimedatectl
command.Set the time zone.
sudo timedatectl set-timezone 'America/Chicago'
Check the new time zone.
timedatectl
Return the time zone to Coordinated Universal Time (UTC).
sudo timedatectl set-timezone 'UTC'
Enable the NTP synchronization.
sudo timedatectl set-ntp yes
After some time, the sync will happen, and the clock will return to the current day and time based on the time zone set.
Use Chrony
chrony is a feature of Oracle Linux that implements NTP to maintain timekeeping accurately on the network and consists of two components, chronyd
and chronyc
. chronyd
is a service daemon that can be enabled and started at boot time, while chronyc
is a command-line utility used to monitor chronyd
's performance and modify its runtime parameters.
Check if chrony is installed.
dnf list chrony
You can install it using
sudo dnf install -y chrony
if you find it not installed.Check the status of the service daemon.
sudo systemctl status chronyd
Enable and start the service using
sudo systemctl enable --now chronyd
if it is inactive. Pressq
to exit thesystemctl
command.Get information about the system clock performance.
chronyc -n tracking
Example Output:
Reference ID : A9FEA9FE (169.254.169.254) Stratum : 3 Ref time (UTC) : Mon Feb 03 16:07:59 2025 System time : 0.000009410 seconds slow of NTP time Last offset : -0.000011537 seconds RMS offset : 0.000015202 seconds Frequency : 22.818 ppm slow Residual freq : -0.004 ppm Skew : 0.222 ppm Root delay : 0.000643811 seconds Root dispersion : 0.000107666 seconds Update interval : 64.4 seconds Leap status : Normal
Where:
- Reference ID: This is the reference ID and name or IP address of the server to which the computer is currently synchronized. The reference ID in the output displays as a hexadecimal number.
- Stratum: The stratum indicates how many hops away this system is from a computer with an attached reference clock.
- Ref time: This is the time in UTC when the system processed the last measurement from the reference source.
Additional information is available by checking the manual page using
man chronyc
.Get a list of sources your system uses.
chronyc -n sources
Using the
-v
option displays column descriptions for each of the columns displayed.
Schedule Tasks
Oracle Linux includes several ways to schedule tasks, and these tasks or jobs can run at the system or user levels. While cron is likely the most well-known of these methods, systemd introduced the more flexible timers in terms of scheduling with the calendar and monotonic time, and it is becoming more widely used. Current Oracle Linux distros have a combination of both.
Using Cron
Check for system-level cron jobs.
sudo ls -al /etc/cron*
The output provides several directories containing executable scripts that perform select tasks on a pre-determined schedule, such as hourly, weekly, and monthly. The
/etc/cron.d
directory also exists where packages can place crontab snippets without modifying the system/etc/crontab
.Get a listing of the system-level cron jobs.
sudo crontab -l
The output indicates there is no crontab for root. Running the same command without
sudo
provides the same output but for the local user account.Create a user-level cronjob.
(crontab -l 2>/dev/null; echo '* * * * * date >> /home/oracle/test') | crontab -
The first command avoids the no crontab message as this is the first job entered, and the second creates the job which runs every minute.
Verify the crontab now exists.
crontab -l
Each job appears on its own line in the crontab. The crontab has five space-separated fields defining the different time periods you can configure, followed by the command the job will run. The command can be equivalent to any command that you can run on the command line on the system, allowing you to run your scripts or to take advantage of pipes and redirection operators. If you want to edit the job, use the
crontab -e
command, which drops you into your default EDITOR,vi
, on Oracle Linux.Check the cron output.
sudo tail /var/log/cron
The output shows the date, time, user, and command run. Since a default minimal installation of Oracle Linux does not install the Mail Transport Agent (MTA), the cron daemon directs the output from commands specified in the crontab to the Syslog daemon. Therefore, you can view the crontab output in the log file at
/var/log/cron
.
Crontab Time Sequence Options
Crontab defines the time fields as:
- minute: From 0 to 59
- hour: From 0 to 23
- day: From 1 to 31
- month: From 1 to 12, or the name of the month
- day-of-week: From 0 to 7, or the abbreviated name of the day. Note that 0 and 7 both represent Sunday.
You can use special characters within any of the time fields:
- Asterisk (*): Specifies that the command should be run for every instance of the field.
- Hyphen (-): Can be used to indicate a range. For example, in the day-of-week field, you might specify 1-5 to schedule the task to run from Monday to Friday but not to run on Saturday or Sunday.
- Comma (,): Can be used to specify a list of values for a field. For example, in the hour field, you might specify 6,18 to schedule the task to run at 6 am and 6 pm.
- Forward slash (/): This can be used to specify step values. For example, you could specify */15 in the minutes field to schedule a task to run every 15 minutes.
The crontab also allows you to use a unique shorthand extension to replace the time fields for general time requirements. Importantly, this shorthand also includes an option to run a command after reboot:
- @reboot : Run once after reboot.
- @yearly : Run once a year, ie. "0 0 1 1 *".
- @annually : Run once a year, ie. "0 0 1 1 *".
- @monthly : Run once a month, ie. "0 0 1 * *".
- @weekly : Run once a week, ie. "0 0 * * 0".
- @daily : Run once a day, ie. "0 0 * * *".
- @hourly : Run once an hour, ie. "0 * * * *".
The crontab only provides 1 minute granularity. If you need finer granular control of your task, it is recommended that you use systemd timers.
Examples:
*/15 * * * * echo "This crontab entry runs every 15 minutes"
10 * * * * echo "This crontab entry runs at 10 minutes past every hour"
30 13 * * 3 echo "This crontab entry runs at 13h30 on every Wednesday"
@reboot echo "This command runs once after a reboot event"
Crontab Command Syntax
The crontab runs under the credentials of the user that the crontab belongs to and runs with some default environment variables set, including:
- HOME: The home directory for the user that the crontab runs as
- LOGNAME: Equivalent to the user name of the user that the crontab runs as
- USER: The user name of the user that the crontab runs as
- SHELL: The shell binary the system uses to run commands. This value is set to
/bin/sh
by default. - PATH: The path available to the crontab utility. This value is set to
/usr/bin:/bin
by default.
You can set alternate environment variables by specifying them as lines within the crontab that do not include time fields, for example, if you would prefer to use the bash shell and you want to regularly import all of the variables and settings within your personal .bashrc
configuration, you may edit your crontab with crontab -e
to look as follows:
SHELL=/bin/bash
* * * * * source $HOME/.bashrc;
Since the crontab job's command runs within a shell environment, standard shell syntax applies and can be used to pipe or redirect output. For example, to redirect all output to /dev/null, use standard shell redirects for the STDOUT and STDERR output on the command:
* * * * * /path/to/command > /dev/null 2>&1
Alternatively, you could redirect output to append to a file that you could use to track the output for each time the command runs:
* * * * * /path/to/command >> $HOME/command.log
Examples:
*/15 * * * * echo "This 'silent' crontab entry runs every 15 minutes but the output is redirected to /dev/null" > /dev/null 2>&1
* * * * * echo "The date and time is $(date +\%Y-\%m-\%d\ \%H:\%M:\%S)" >> $HOME/crontab.log
The example escapes the %
characters in the date command because %
characters are changed into newline characters by the crontab utility, and all data after the first %
is sent to the command as standard input. See man 5 crontab
for more information.
Remove The Crontab File
If you only plan to remove a specific job, you can use the crontab -e
command to edit and remove the individual line containing that job. However, if you want to remove all the jobs, crontab
provides a quick and efficient option.
Remove all of your cron job entries.
crontab -r
Systemd Timers
Like cron jobs, systemd timers allow running commands or scripts at a specific time. However, these tasks are controlled and supervised by systemd and have finer grain control of the time-based activation.
List existing timers.
systemctl status *timer
Press
q
to exit thesystemctl
command.
Create a Timer
A timer consists of a service unit that defines the work to do and a timer unit to schedule and trigger it. Since these are systemd service units, you can create them in the system or user space. The benefit of user space is that it allows users to manage their services, such as daemons and automated tasks.
Create the local user's systemd directory.
mkdir -p ~/.config/systemd/user
System-level service units and timers go into
/etc/systemd/system
.Enable lingering for the current user.
loginctl enable-linger $(whoami)
Lingering refers to a feature in systemd that allows user processes to continue running even after the user logs out of their session.
Verify the user's linger status.
loginctl user-status $(whoami)
Press
q
to exit the loginctl command.Write a script for the timer to run.
cat << 'EOF' | tee ~/test.sh > /dev/null #!/bin/bash /usr/bin/echo "test from test.service: $(date)" 2>&1 | tee -a /home/oracle/test.log EOF
Make the script executable.
chmod +x ~/test.sh
Create a service unit.
cat << EOF | tee ~/.config/systemd/user/test.service > /dev/null [Unit] Description=Run the test script StartLimitIntervalSec=1 StartLimitBurst=10 [Service] Type=oneshot ExecStart=/home/oracle/test.sh StandardOutput=journal SyslogIdentifier=test EOF
The service requires
StartLimitIntervalSec
andStartLimitBurst
as it is intended to run this service every few seconds. You can learn more about these parameters inman systemd.unit
.Create a timer unit.
cat << EOF | tee ~/.config/systemd/user/test.timer > /dev/null [Unit] Description=Run test.service every 10 seconds [Timer] OnCalendar=*:*:0/10 AccuracySec=1 Persistent=true [Install] WantedBy=timers.target EOF
The
AccuracySec
parameter is required because systemd timers do not execute exactly when requested but operate on a default variance of one minute.Make systemd aware of the changes.
systemctl --user daemon-reload
Enable and start the timer.
systemctl --user enable --now test.timer
Verify the timer is running.
systemctl --user status test.timer --no-pager
The
--no-pager
option prints the full output without the need to scroll or page through the entries. Check outsystemctl --help
for additional options.Check the bash script's log file.
cat ~/test.log
Check the systemd journal.
journalctl -r -n 10 --user-unit test --no-pager
This output shows the last 10 lines of output from the user's test.service systemd unit. The
-r
option displays the journal entries in reverse chronological order.journalctl -r -n 10 -t test --no-pager
This command shows the output generated by the script run by the systemd service unit. The
-t
option matches theSyslogIdentifier
defined in thetest.service
file, which provides an identifier to search on. See more options forjournalctl
by reading theman journalctl
page.Disable the timer.
systemctl --user disable test.timer
This command prevents the timer from starting automatically in the future and making it inactive.
Stop the timer.
systemctl --user stop test.timer
This command halts the current execution of the timer if it is running. It does not prevent the timer from starting again in the future.
Next Steps
By completing this tutorial, you've demonstrated your skills and ability to manage the date, time, and schedule tasks on Oracle Linux. There are many more flags and features of the commands shown. Check out the links below and the suggested man pages to increase your knowledge and skills.