Manage System Time and Schedule Tasks on Oracle Linux

5
0
Send lab feedback

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, and timedatectl
  • 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.

  1. Open a terminal on the Luna Desktop.

  2. Clone the linux-virt-labs GitHub project.

    git clone https://github.com/oracle-devrel/linux-virt-labs.git
  3. Change into the working directory.

    cd linux-virt-labs/ol
  4. Install the required collections.

    ansible-galaxy collection install -r requirements.yml
  5. 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 sets ansible_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

  1. Open a terminal and connect via SSH to the ol-node-01 instance.

    ssh oracle@<ip_address_of_instance>
  2. 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 running date --help or view the manual page using man date.

  3. Adjust the system time and date.

    sudo date -s "1 JAN 1970 16:00:00"
  4. 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.

  5. 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

  1. Read the current hardware clock (RTC).

    sudo hwclock --show
  2. 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 running hwclock --help or viewing the manual page man hwclock.

Date and Time Using Systemd

  1. 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.

  2. Disable the NTP synchronization.

    sudo timedatectl set-ntp no
  3. Set the date and time.

    sudo timedatectl set-time '2014-09-23 14:10:40'
  4. Check the date and time.

    date
  5. Get a list of time zones.

    timedatectl list-timezones

    Press q to exit the timedatectl command.

  6. Set the time zone.

    sudo timedatectl set-timezone 'America/Chicago'
  7. Check the new time zone.

    timedatectl
  8. Return the time zone to Coordinated Universal Time (UTC).

    sudo timedatectl set-timezone 'UTC'
  9. 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.

  1. Check if chrony is installed.

    dnf list chrony

    You can install it using sudo dnf install -y chrony if you find it not installed.

  2. 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. Press q to exit the systemctl command.

  3. 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.

  4. 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

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  1. 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.

  1. List existing timers.

    systemctl status *timer

    Press q to exit the systemctl 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.

  1. Create the local user's systemd directory.

    mkdir -p ~/.config/systemd/user

    System-level service units and timers go into /etc/systemd/system.

  2. 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.

  3. Verify the user's linger status.

    loginctl user-status $(whoami)

    Press q to exit the loginctl command.

  4. 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
  5. Make the script executable.

    chmod +x ~/test.sh
  6. 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 and StartLimitBurst as it is intended to run this service every few seconds. You can learn more about these parameters in man systemd.unit.

  7. 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.

  8. Make systemd aware of the changes.

    systemctl --user daemon-reload
  9. Enable and start the timer.

    systemctl --user enable --now test.timer
  10. 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 out systemctl --help for additional options.

  11. Check the bash script's log file.

    cat ~/test.log
  12. 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 the SyslogIdentifier defined in the test.service file, which provides an identifier to search on. See more options for journalctl by reading the man journalctl page.

  13. Disable the timer.

    systemctl --user disable test.timer

    This command prevents the timer from starting automatically in the future and making it inactive.

  14. 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.

SSR