How to Set Linux Time Zone and NTP Settings with Shell Scripting

Accurate system time is the quiet backbone of enterprise IT. Authentication protocols, certificates, distributed logging, and scheduled maintenance all depend on synchronized clocks. This post walks through a production-ready shell script to set the time zone in Linux and NTP timedatectl settings using systemd-timesyncd and timedatectl. If you manage fleets of Linux endpoints—or build policy as an MSP—this is the kind of repeatable automation that keeps incidents out of your pager.

Background

Linux offers multiple ways to manage time: classic ntpd, chrony, and systemd-timesyncd. Many modern distros ship with systemd-timesyncd enabled by default, and timedatectl provides a consistent interface. The script you provided standardizes three tasks IT teams do regularly:

  • List and set the system time zone (e.g., America/Los_Angeles)
  • Configure one or two NTP servers for synchronization
  • Tune NTP polling intervals to match network and compliance requirements

It includes robust validation, safety checks, and idempotent behavior so you can run it repeatedly without creating drift.

The Script

#!/usr/bin/env bash
#
# Description: Set the time zone and NTP timedatectl settings for the local machine.
# By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
# Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
# Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
# Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
# Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
# Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
# Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
# EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#
# Preset Parameter: --listTimeZones|-l
#		Lists all the time zones available to set.
#
# Preset Parameter: --setTimeZone|-t <arg>
#		Specifies the name of the time zone you would like to set, such as 'America/Los_Angeles'.
#
# Preset Parameter: --setSyncServers|-s <arg>
#		Specifies up to two NTP servers (comma-separated) to synchronize the time with.
#
# Preset Parameter: --syncIntervalMinimumInSeconds|--min <arg>
#		Specifies the minimum interval in seconds for NTP synchronization. The default value for most distributions is 32 seconds.
#
# Preset Parameter: --syncIntervalMaximumInSeconds|--max <arg>
#		Specifies the maximum interval in seconds for NTP synchronization. The default value for most distributions is 2048 seconds.
#
# Preset Parameter: --help|-h
#		Displays this help menu.
#
# Example: --setTimeZone "America/Los_Angeles" --setSyncServers "0.pool.ntp.org" --syncIntervalMinimumInSeconds "32" --syncIntervalMaximumInSeconds "2048"
#
# The current time zone is already set to 'America/Los_Angeles'.
#
# Analyzing the default timedatectl configuration file at '/etc/systemd/timesyncd.conf'.
# The current primary sync server is not currently set.
# The current fallback sync server is not currently set.
# The current minimum sync interval is not currently set.
# The current maximum sync interval is not currently set.
# An update to the current timedatectl configuration file is necessary.
#
# Creating a new timedatectl configuration file at '/etc/systemd/timesyncd.conf.d/1752702365-ntp.conf'.
# Setting primary sync server to '0.pool.ntp.org'.
# Setting minimum sync interval to '32' seconds.
# Setting maximum sync interval to '2048' seconds.
# Successfully created a new timedatectl configuration file.
# Restarting systemd-timesyncd.
# Successfully updated the NTP configuration.
#
# ### Previous timedatectl Settings ###
# Timezone: America/Los_Angeles
# # /etc/systemd/timesyncd.conf
# [Time]
#
# ### Current timedatectl Settings ###
# Timezone: America/Los_Angeles
# # /etc/systemd/timesyncd.conf
# [Time]
#
# # /etc/systemd/timesyncd.conf.d/1752702365-ntp.conf
# [Time]
# NTP=0.pool.ntp.org
# PollIntervalMinSec=32
# PollIntervalMaxSec=2048
#
# ### Current Time ###
# 07/16/2025 02:46:05 PM
#
# Version: 1.0
# Release Notes: Initial Release

_arg_setTimeZone=
_arg_setSyncServers=
_arg_syncServers=
_arg_syncIntervalMinimumInSeconds=
_arg_syncIntervalMaximumInSeconds=
_arg_listTimeZones="off"
exitCode=0

print_help() {
  printf '\n\n%s\n\n' 'Usage: [--listTimeZones|-l] [--setTimeZone|-t <arg>] [--setSyncServers|-s <arg>] [--syncIntervalMinimumInSeconds|--min <arg>] [--syncIntervalMaximumInSeconds|--max <arg>] [--help|-h]'
  printf '%s\n' 'Preset Parameter: --listTimeZones|-l'
  printf '\t%s\n' "Lists all the time zones available to set."
  printf '%s\n' 'Preset Parameter: --setTimeZone|-t <arg>'
  printf '\t%s\n' "Specifies the name of the time zone you would like to set, such as 'America/Los_Angeles'."
  printf '%s\n' 'Preset Parameter: --setSyncServers|-s <arg>'
  printf '\t%s\n' "Specifies up to two NTP servers (comma-separated) to synchronize the time with."
  printf '%s\n' 'Preset Parameter: --syncIntervalMinimumInSeconds|--min <arg>'
  printf '\t%s\n' "Specifies the minimum interval in seconds for NTP synchronization. The default value for most distributions is 32 seconds."
  printf '%s\n' 'Preset Parameter: --syncIntervalMaximumInSeconds|--max <arg>'
  printf '\t%s\n' "Specifies the maximum interval in seconds for NTP synchronization. The default value for most distributions is 2048 seconds."
  printf '%s\n' 'Preset Parameter: --help|-h'
  printf '\t%s\n' "Displays this help menu."
}

die() {
  local _ret="${2:-1}"
  echo "$1" >&2
  test "${_PRINT_HELP:-no}" = yes && print_help >&2
  exit "${_ret}"
}

parse_commandline() {
  while test $# -gt 0; do
    _key="$1"
    case "$_key" in
      --setTimeZone | --settimezone | -t)
        test $# -lt 2 && die "[Error] Missing value for the optional argument '$_key'." 1
        _arg_setTimeZone=$2
        shift
        ;;
      --setTimeZone=*)
        _arg_setTimeZone="${_key##--setTimeZone=}"
        ;;
      --setSyncServers | --setsyncservers | --setSyncServer | --setsyncserver | -s)
        test $# -lt 2 && die "[Error] Missing value for the optional argument '$_key'." 1
        _arg_setSyncServers=$2
        shift
        ;;
      --setSyncServers=*)
        _arg_setSyncServers="${_key##--setSyncServers=}"
        ;;
      --syncIntervalMinimumInSeconds | --syncintervalminimum | --syncMinimum | --syncminimum | --min)
        test $# -lt 2 && die "[Error] Missing value for the optional argument '$_key'." 1
        _arg_syncIntervalMinimumInSeconds=$2
        shift
        ;;
      --syncIntervalMinimumInSeconds=*)
        _arg_syncIntervalMinimumInSeconds="${_key##--syncIntervalMinimumInSeconds=}"
        ;;
      --syncIntervalMaximumInSeconds | --syncintervalmaximum | --syncMaximum | --syncmaximum | --max)
        test $# -lt 2 && die "[Error] Missing value for the optional argument '$_key'." 1
        _arg_syncIntervalMaximumInSeconds=$2
        shift
        ;;
      --syncIntervalMaximumInSeconds=*)
        _arg_syncIntervalMaximumInSeconds="${_key##--syncIntervalMaximumInSeconds=}"
        ;;
      --listTimeZones | --listtimezones | -l)
        _arg_listTimeZones="on"
        ;;
      --help | -h)
        _PRINT_HELP=yes die
        ;;
      *)
        _PRINT_HELP=yes die "[Error] Got an unexpected argument '$1'" 1
        ;;
    esac
    shift
  done
}

echo " "
parse_commandline "$@"

# If script form variables are used, replace the command line paramters with their value
if [[ -n $listTimeZones && $listTimeZones == "true" ]]; then
  _arg_listTimeZones="on"
fi

if [[ -n $setTimeZone ]]; then
  _arg_setTimeZone="$setTimeZone"
fi

if [[ -n $setSyncServers ]]; then
  _arg_setSyncServers="$setSyncServers"
fi

if [[ -n $syncIntervalMinimumInSeconds ]]; then
  _arg_syncIntervalMinimumInSeconds="$syncIntervalMinimumInSeconds"
fi

if [[ -n $syncIntervalMaximumInSeconds ]]; then
  _arg_syncIntervalMaximumInSeconds="$syncIntervalMaximumInSeconds"
fi

# Ensure the script is run with root permissions
if [[ $(id -u) -ne 0 ]]; then
  _PRINT_HELP=no die "[Error] This script must be run with root permissions. Try running it with sudo or as the system/root user." 1
fi

# Check if the timedatectl command is available
if ! command -v "timedatectl" 1> /dev/null; then
  _PRINT_HELP=no die "[Error] This script is designed to configure the time settings in timedatectl, but it was not found.
[Error] You may want to check your distribution's documentation to see the proper way of configuring the system time." 1
fi

if [[ $_arg_listTimeZones == "off" ]]; then
  if ! systemctl is-enabled systemd-timesyncd 1> /dev/null; then
    _PRINT_HELP=no die "[Error] The service 'systemd-timesyncd' is currently disabled. In order to adjust the timedatectl settings you must have it enabled." 1
  fi
fi

# You must provide at least one option
if [[ $_arg_listTimeZones == "off" && -z $_arg_setTimeZone && -z $_arg_setSyncServers && -z $_arg_syncIntervalMinimumInSeconds && -z $_arg_syncIntervalMaximumInSeconds ]]; then
  _PRINT_HELP=yes die "[Error] You must provide at least one valid option." 1
fi

# Validate that 'List Time Zones' is not used with other options
if [[ $_arg_listTimeZones == "on" && (-n $_arg_setTimeZone || -n $_arg_setSyncServers || -n $_arg_syncIntervalMinimumInSeconds || -n $_arg_syncIntervalMaximumInSeconds) ]]; then
  _PRINT_HELP=yes die "[Error] 'List Time Zones' cannot be used with other options." 1
fi

# Validate the specified time zone
if [[ -n $_arg_setTimeZone ]]; then
  _arg_setTimeZone=$(echo "$_arg_setTimeZone" | xargs)

  if [[ -z $_arg_setTimeZone ]]; then
    _PRINT_HELP=yes die "[Error] You must specify a valid time zone to set." 1
  fi

  validTimeZones=$(timedatectl list-timezones --no-pager)
  if ! echo "$validTimeZones" | grep -q -x "$_arg_setTimeZone"; then
    _PRINT_HELP=yes die "[Error] The time zone '$_arg_setTimeZone' is invalid. You must specify a valid time zone to set.
### Valid Time Zones ###
$validTimeZones" 1
  fi
fi

# Validate NTP configuration if sync servers or intervals are specified
if [[ -n $_arg_setSyncServers || -n $_arg_syncIntervalInMinutes ]]; then
  if ! timedatectl show 1> /dev/null; then
    _PRINT_HELP=no die "[Error] Unable to verify if this version of timedatectl is capable of using NTP." 1
  fi

  if timedatectl show | grep "CanNTP=" | grep "no" 1> /dev/null 2> /dev/null; then
    _PRINT_HELP=no die "[Error] This system does not currently have NTP installed and configured with timedatectl. Unable to configure network time synchronization." 1
  fi
fi

# Validate and process sync servers
if [[ -n $_arg_setSyncServers ]]; then
  _arg_setSyncServers=$(echo "$_arg_setSyncServers" | xargs)

  if [[ -z $_arg_setSyncServers ]]; then
    _PRINT_HELP=yes die "[Error] You must specify a valid sync server to set." 1
  fi

  _arg_syncServers=$(echo "$_arg_setSyncServers" | tr "," "\n" | sed "s/^[[:space:]]//" | sed "s/[[:space:]]$//")

  serverCount=$(echo "$_arg_syncServers" | wc -l | xargs)
  if [[ $serverCount -gt 2 ]]; then
    _PRINT_HELP=yes die "[Error] You can only specify up to two valid sync servers." 1
  fi

  if invalidServers=$(echo "$_arg_syncServers" | grep -e "[^a-zA-Z0-9.:_-]"); then
    _PRINT_HELP=yes die "[Error] One or more of the sync servers you specified are invalid. They contain invalid characters; only alphanumeric characters or one of these symbols are valid '.:_-'.
### Invalid Servers ###
$invalidServers" 1
  fi

  # Check if sync servers are responsive on UDP port 123
  while IFS= read -r syncServer; do
    if ! timeout 30 bash -c "echo -n '' > /dev/udp/$syncServer/123"; then
      _PRINT_HELP=yes die "[Error] The sync server '$syncServer' was not responsive on UDP port 123 (NTP). Unable to set sync server." 1
    fi
  done <<< "$_arg_syncServers"

  # Assign primary and fallback sync servers
  primarySyncServer=$(echo "$_arg_syncServers" | head -n 1)
  if [[ $serverCount -gt 1 ]]; then
    fallbackSyncServer=$(echo "$_arg_syncServers" | tail -n 1)
  fi
fi

# Validate and process minimum sync interval
if [[ -n $_arg_syncIntervalMinimumInSeconds ]]; then
  _arg_syncIntervalMinimumInSeconds=$(echo "$_arg_syncIntervalMinimumInSeconds" | xargs)

  if [[ -z $_arg_syncIntervalMinimumInSeconds ]]; then
    _PRINT_HELP=yes die "[Error] You must specify a valid minimum sync interval to set." 1
  fi

  if [[ $_arg_syncIntervalMinimumInSeconds =~ [^0-9] ]]; then
    _PRINT_HELP=yes die "[Error] The sync interval minimum '$_arg_syncIntervalMinimumInSeconds' is invalid. It contains invalid characters; only numeric characters are allowed." 1
  fi

  if [[ $_arg_syncIntervalMinimumInSeconds -lt 1 || $_arg_syncIntervalMinimumInSeconds -gt 86400 ]]; then
    _PRINT_HELP=yes die "[Error] The sync interval minimum '$_arg_syncIntervalMinimumInSeconds' is invalid. The sync interval must be greater than or equal to 1 and less than or equal to 86400." 1
  fi
fi

# Validate and process maximum sync interval
if [[ -n $_arg_syncIntervalMaximumInSeconds ]]; then
  _arg_syncIntervalMaximumInSeconds=$(echo "$_arg_syncIntervalMaximumInSeconds" | xargs)

  if [[ -z $_arg_syncIntervalMaximumInSeconds ]]; then
    _PRINT_HELP=yes die "[Error] You must specify a valid maximum sync interval to set." 1
  fi

  if [[ $_arg_syncIntervalMaximumInSeconds =~ [^0-9] ]]; then
    _PRINT_HELP=yes die "[Error] The sync interval maximum '$_arg_syncIntervalMaximumInSeconds' is invalid. It contains invalid characters; only numeric characters are allowed." 1
  fi

  if [[ $_arg_syncIntervalMaximumInSeconds -lt 1 || $_arg_syncIntervalMaximumInSeconds -gt 86400 ]]; then
    _PRINT_HELP=yes die "[Error] The sync interval maximum '$_arg_syncIntervalMaximumInSeconds' is invalid. The sync interval must be greater than or equal to 1 and less than or equal to 86400." 1
  fi
fi

# Ensure minimum sync interval is less than maximum sync interval
if [[ -n $_arg_syncIntervalMinimumInSeconds && -n $_arg_syncIntervalMaximumInSeconds && $_arg_syncIntervalMinimumInSeconds -gt $_arg_syncIntervalMaximumInSeconds ]]; then
  _PRINT_HELP=yes die "[Error] The maximum sync interval '$_arg_syncIntervalMaximumInSeconds' is less than the minimum sync interval '$_arg_syncIntervalMinimumInSeconds'. The minimum sync interval must be less than the max sync interval." 1
fi

if ! currentConfig=$(systemd-analyze cat-config systemd/timesyncd.conf --no-pager); then
  echo "[Error] Failed to retrieve the current time settings." >&2
  exitCode=1
fi
previousTimeSettings=$(echo "$currentConfig" | awk '/^# \/.*\.conf/ { print; next } /^\s*#/ { next } { print }')

# List time zones if requested
if [[ $_arg_listTimeZones == "on" ]]; then
  if ! currentTimeZone=$(timedatectl show | grep "Timezone=" | sed "s/Timezone=//" | sed "s/^[[:space:]]*//g" | sed "s/[[:space:]]*$//g"); then
    _PRINT_HELP=no die "[Error] Failed to retrieve the current timezone." 1
  fi

  # Display the current time zone.
  echo ""
  echo "The current timezone is '$currentTimeZone'."
  echo ""

  echo "### Valid Time Zones ###"
  if ! timedatectl list-timezones --no-pager; then
    _PRINT_HELP=no die "[Error] Failed to retrieve a list of valid time zones." 1
  fi

  exit "$exitCode"
fi

# Set the time zone if specified
if [[ -n $_arg_setTimeZone ]]; then
  if ! previousTimeZone=$(timedatectl show | grep "Timezone=" | sed "s/Timezone=//" | sed "s/^[[:space:]]*//g" | sed "s/[[:space:]]*$//g"); then
    _PRINT_HELP=no die "[Error] Failed to retrieve the current timezone." 1
  fi

  alreadySetTimeZone="false"

  if [[ $previousTimeZone == "$_arg_setTimeZone" ]]; then
    echo "The current time zone is already set to '$_arg_setTimeZone'."
    alreadySetTimeZone="true"
  else
    echo "Changing the timezone from '$previousTimeZone' to '$_arg_setTimeZone'."

    if ! timedatectl set-timezone "$_arg_setTimeZone"; then
      _PRINT_HELP=no die "[Error] Failed to set the time zone to '$_arg_setTimeZone'." 1
    fi
  fi

  currentTimeZone=$(timedatectl show | grep "Timezone=" | sed "s/Timezone=//" | sed "s/^[[:space:]]*//g" | sed "s/[[:space:]]*$//g")

  if [[ $alreadySetTimeZone == "false" && $currentTimeZone == "$_arg_setTimeZone" ]]; then
    echo "Successfully set the time zone to '$_arg_setTimeZone'."
  elif [[ $alreadySetTimeZone == "false" ]]; then
    _PRINT_HELP=no die "[Error] Failed to set the time zone to '$_arg_setTimeZone'." 1
  fi

  echo ""
fi

# Create the configuration directory if it doesn't exist
if [[ ! -d "/etc/systemd/timesyncd.conf.d" && (-n $_arg_syncServers || -n $_arg_syncIntervalMinimumInSeconds || -n $_arg_syncIntervalMaximumInSeconds) ]]; then
  if ! mkdir "/etc/systemd/timesyncd.conf.d"; then
    _PRINT_HELP=no die "[Error] Failed to create the directory '/etc/systemd/timesyncd.conf.d'." 1
  fi
fi

# Check if there are existing configuration files in the timesyncd configuration directory
timeSyncConfigFiles=$(ls /etc/systemd/timesyncd.conf.d/*.conf 2> /dev/null)

# If no configuration files exist and the default configuration file is present, analyze it
if [[ -z $timeSyncConfigFiles && -f "/etc/systemd/timesyncd.conf" && (-n $_arg_syncServers || -n $_arg_syncIntervalMinimumInSeconds || -n $_arg_syncIntervalMaximumInSeconds) ]]; then
  echo "Analyzing the default timedatectl configuration file at '/etc/systemd/timesyncd.conf'."

  # Check and update primary and fallback sync servers if necessary
  if [[ -n $_arg_syncServers ]]; then
    currentPrimarySyncServer=$(grep -w -r -H "^NTP" /etc/systemd/timesyncd.conf)
    currentPrimarySyncServer=$(echo "$currentPrimarySyncServer" | grep -v '^$')
    currentPrimaryServerCount=$(echo "$currentPrimarySyncServer" | awk 'NF' | wc -l | xargs)

    currentFallbackSyncServer=$(grep -w -r -H "^FallbackNTP" /etc/systemd/timesyncd.conf)
    currentFallbackSyncServer=$(echo "$currentFallbackSyncServer" | grep -v '^$')
    currentFallbackServerCount=$(echo "$currentFallbackSyncServer" | awk 'NF' | wc -l | xargs)

    # Ensure there are no duplicate primary or fallback sync servers
    if [[ $currentPrimaryServerCount -gt 1 ]]; then
      _PRINT_HELP=no die "[Error] Multiple primary sync servers were found. Please correct this before attempting to adjust the sync servers.
$currentPrimarySyncServer" 1
    fi

    if [[ $currentFallbackServerCount -gt 1 ]]; then
      _PRINT_HELP=no die "[Error] Multiple fallback sync servers were found. Please correct this before attempting to adjust the sync servers.
$currentPrimarySyncServer" 1
    fi

    # Check if the primary sync server needs to be updated
    if [[ -n $currentPrimarySyncServer ]]; then
      if ! echo "$currentPrimarySyncServer" | grep -w "$primarySyncServer" 1> /dev/null 2> /dev/null; then
        currentPrimarySyncValue=$(echo "$currentPrimarySyncServer" | awk -F "=" '{print $2}')

        echo "The current primary sync server needs to be updated from '$currentPrimarySyncValue' to '$primarySyncServer'."
        updateTimeSyncConfig="true"
      else
        echo "The current primary sync server is already $primarySyncServer."
      fi
    else
      echo "The current primary sync server is not currently set."
      updateTimeSyncConfig="true"
    fi

    # Check if the fallback sync server needs to be updated
    if [[ -n $currentFallbackSyncServer ]]; then
      if ! echo "$currentFallbackSyncServer" | grep -w "$fallbackSyncServer" 1> /dev/null 2> /dev/null; then
        currentFallbackSyncValue=$(echo "$currentFallbackSyncServer" | awk -F "=" '{print $2}')

        echo "The current fallback sync server needs to be updated from '$currentFallbackSyncValue' to '$fallbackSyncServer'."
        updateTimeSyncConfig="true"
      else
        echo "The current fallback sync server is already $fallbackSyncServer."
      fi
    else
      echo "The current fallback sync server is not currently set."
      updateTimeSyncConfig="true"
    fi
  fi

  # Check and update the minimum sync interval if necessary
  if [[ -n $_arg_syncIntervalMinimumInSeconds ]]; then
    currentMinimumSyncInterval=$(grep -w -r -H "^PollIntervalMinSec" /etc/systemd/timesyncd.conf)
    currentMinimumSyncInterval=$(echo "$currentMinimumSyncInterval" | grep -v '^$')
    currentMinimumSyncIntervalCount=$(echo "$currentMinimumSyncInterval" | awk 'NF' | wc -l | xargs)

    currentMaximumSyncInterval=$(grep -w -r -H "^PollIntervalMaxSec" /etc/systemd/timesyncd.conf)
    currentMaximumSyncInterval=$(echo "$currentMaximumSyncInterval" | grep -v '^$')
    currentMaximumSyncIntervalCount=$(echo "$currentMaximumSyncInterval" | awk 'NF' | wc -l | xargs)

    # Ensure there are no duplicate minimum or maximum sync intervals
    if [[ $currentMinimumSyncIntervalCount -gt 1 ]]; then
      _PRINT_HELP=no die "[Error] Multiple minimum sync intervals were found. Please correct this before attempting to adjust the minimum sync interval.
$currentMinimumSyncInterval" 1
    fi

    if [[ $currentMaximumSyncIntervalCount -gt 1 ]]; then
      _PRINT_HELP=no die "[Error] Multiple maximum sync intervals were found. Please correct this before attempting to adjust the minimum sync interval.
$currentMaximumSyncInterval" 1
    fi

    # Validate the relationship between minimum and maximum sync intervals
    if [[ -n $currentMaximumSyncInterval && -z $_arg_syncIntervalMaximumInSeconds ]]; then
      currentMaxValue=$(echo "$currentMaximumSyncInterval" | awk -F "=" '{ print $2 }')

      if [[ currentMaxValue -lt $_arg_syncIntervalMinimumInSeconds ]]; then
        _PRINT_HELP=yes die "[Error] The maximum sync interval '$_arg_syncIntervalMaximumInSeconds' is less than the minimum sync interval '$_arg_syncIntervalMinimumInSeconds'. The minimum sync interval must be less than the max sync interval." 1
      fi
    fi

    # Check if the minimum sync interval needs to be updated
    if [[ -n $currentMinimumSyncInterval ]]; then
      if ! echo "$currentMinimumSyncInterval" | grep -w "$_arg_syncIntervalMinimumInSeconds" 1> /dev/null 2> /dev/null; then
        currentMinValue=$(echo "$currentMinimumSyncInterval" | awk -F "=" '{ print $2 }')

        echo "The current minimum sync interval needs to be updated from '$currentMinValue' to '$_arg_syncIntervalMinimumInSeconds'."
        updateTimeSyncConfig="true"
      else
        echo "The current minimum sync interval is already $_arg_syncIntervalMinimumInSeconds."
      fi
    else
      echo "The current minimum sync interval is not currently set."
      updateTimeSyncConfig="true"
    fi
  fi

  # Check and update the maximum sync interval if necessary
  if [[ -n $_arg_syncIntervalMaximumInSeconds ]]; then
    currentMaximumSyncInterval=$(grep -w -r -H "^PollIntervalMaxSec" /etc/systemd/timesyncd.conf)
    currentMaximumSyncInterval=$(echo "$currentMaximumSyncInterval" | grep -v '^$')
    currentMaximumSyncIntervalCount=$(echo "$currentMaximumSyncInterval" | awk 'NF' | wc -l | xargs)

    currentMinimumSyncInterval=$(grep -w -r -H "^PollIntervalMinSec" /etc/systemd/timesyncd.conf)
    currentMinimumSyncInterval=$(echo "$currentMinimumSyncInterval" | grep -v '^$')
    currentMinimumSyncIntervalCount=$(echo "$currentMinimumSyncInterval" | awk 'NF' | wc -l | xargs)

    # Ensure there are no duplicate maximum or minimum sync intervals
    if [[ $currentMaximumSyncIntervalCount -gt 1 ]]; then
      _PRINT_HELP=no die "[Error] Multiple maximum sync intervals were found. Please correct this before attempting to adjust the maximum sync interval.
$currentMaximumSyncInterval" 1
    fi

    if [[ $currentMinimumSyncIntervalCount -gt 1 ]]; then
      _PRINT_HELP=no die "[Error] Multiple minimum sync intervals were found. Please correct this before attempting to adjust the maximum sync interval.
$currentMinimumSyncInterval" 1
    fi

    # Validate the relationship between maximum and minimum sync intervals
    if [[ -n $currentMinimumSyncInterval && -z $_arg_syncIntervalMinimumInSeconds ]]; then
      currentMinValue=$(echo "$currentMinimumSyncInterval" | awk -F "=" '{ print $2 }')

      if [[ currentMinValue -gt $_arg_syncIntervalMaximumInSeconds ]]; then
        _PRINT_HELP=yes die "[Error] The maximum sync interval '$_arg_syncIntervalMaximumInSeconds' is less than the minimum sync interval '$_arg_syncIntervalMinimumInSeconds'. The minimum sync interval must be less than the max sync interval." 1
      fi
    fi

    # Check if the maximum sync interval needs to be updated
    if [[ -n $currentMaximumSyncInterval ]]; then
      if ! echo "$currentMaximumSyncInterval" | grep -w "$_arg_syncIntervalMaximumInSeconds" 1> /dev/null 2> /dev/null; then
        currentMaxValue=$(echo "$currentMaximumSyncInterval" | awk -F "=" '{ print $2 }')

        echo "The current maximum sync interval needs to be updated from '$currentMaxValue' to '$_arg_syncIntervalMaximumInSeconds'."
        updateTimeSyncConfig="true"
      else
        echo "The current maximum sync interval is already $_arg_syncIntervalMaximumInSeconds."
      fi
    else
      echo "The current maximum sync interval is not currently set."
      updateTimeSyncConfig="true"
    fi
  fi

  # Determine if an update to the configuration file is necessary
  if [[ $updateTimeSyncConfig == "true" ]]; then
    echo "An update to the current timedatectl configuration file is necessary."
  else
    echo "No update is necessary at this time."
    echo ""

    echo "### Previous timedatectl Settings ###"
    echo "Timezone: $previousTimeZone"
    echo "$previousTimeSettings"

    echo ""

    if ! currentTimeZone=$(timedatectl show | grep "Timezone=" | sed "s/Timezone=//" | sed "s/^[[:space:]]*//g" | sed "s/[[:space:]]*$//g"); then
      echo "[Error] Failed to retrieve the current timezone." >&2
      exitCode=1
    fi

    echo "### Current timedatectl Settings ###"
    echo "Timezone: $currentTimeZone"
    if ! currentConfig=$(systemd-analyze cat-config systemd/timesyncd.conf --no-pager); then
      echo "[Error] Failed to retrieve the current time settings." >&2
      exitCode=1
    fi
    echo "$currentConfig" | awk '/^# \/.*\.conf/ { print; next } /^\s*#/ { next } { print }'

    echo ""

    echo "### Current Time ###"
    if ! date "+%x %r"; then
      echo "[Error] Failed to retrieve the current time." >&2
      exitCode=1
    fi

    exit "$exitCode"
  fi

  echo ""
fi

# If no configuration files exist and an update is necessary, create a new configuration file
if [[ -z $timeSyncConfigFiles && $updateTimeSyncConfig == "true" ]]; then
  timestamp=$(date "+%s")
  ntpFilePath="/etc/systemd/timesyncd.conf.d/$timestamp-ntp.conf"
  echo "Creating a new timedatectl configuration file at '$ntpFilePath'."

  # Write the new configuration file
  exec 3>&1
  {
    echo "[Time]"
    if [[ -n $_arg_syncServers ]]; then
      echo "NTP=$primarySyncServer"
      echo "Setting primary sync server to '$primarySyncServer'." >&3
      if [[ -n $fallbackSyncServer ]]; then
        echo "FallbackNTP=$fallbackSyncServer"
        echo "Setting fallback sync server to '$fallbackSyncServer'." >&3
      else
        echo "#FallbackNTP=ntp.ubuntu.com"
      fi
    else
      echo "#NTP="
      echo "#FallbackNTP=ntp.ubuntu.com"
    fi
    echo "#RootDistanceMaxSec=5"
    if [[ -n $_arg_syncIntervalMinimumInSeconds ]]; then
      echo "PollIntervalMinSec=$_arg_syncIntervalMinimumInSeconds"
      echo "Setting minimum sync interval to '$_arg_syncIntervalMinimumInSeconds' seconds." >&3
    else
      echo "#PollIntervalMinSec=32"
    fi
    if [[ -n $_arg_syncIntervalMaximumInSeconds ]]; then
      echo "PollIntervalMaxSec=$_arg_syncIntervalMaximumInSeconds"
      echo "Setting maximum sync interval to '$_arg_syncIntervalMaximumInSeconds' seconds." >&3
    else
      echo "#PollIntervalMaxSec=2048"
    fi
    echo "#ConnectionRetrySec=30"
    echo "#SaveIntervalSec=60"
  } > "$ntpFilePath"

  # Validate the creation of the new configuration file
  if [[ ! -s $ntpFilePath ]]; then
    _PRINT_HELP=no die "[Error] Failed to create the file '$ntpFilePath'. Unable to set sync servers or configure the sync interval." 1
  else
    echo "Successfully created a new timedatectl configuration file."

    # Enable NTP if it is currently disabled
    if timedatectl show | grep -w "NTP" | grep "no" 1> /dev/null; then
      echo "Turning on NTP."
      if ! timedatectl set-ntp true; then
        _PRINT_HELP=no die "[Error] Failed to turn on NTP." 1
      fi
    fi

    # Restart the systemd-timesyncd service to apply changes
    echo "Restarting systemd-timesyncd."
    if ! systemctl daemon-reload; then
      _PRINT_HELP=no die "[Error] Failed to run 'systemctl daemon-reload'." 1
    fi

    if ! systemctl restart systemd-timesyncd; then
      _PRINT_HELP=no die "[Error] Failed to restart 'systemd-timesyncd'." 1
    fi

    echo "Successfully updated the NTP configuration."

    echo ""
    echo "### Previous timedatectl Settings ###"
    echo "Timezone: $previousTimeZone"
    echo "$previousTimeSettings"

    echo ""

    if ! currentTimeZone=$(timedatectl show | grep "Timezone=" | sed "s/Timezone=//" | sed "s/^[[:space:]]*//g" | sed "s/[[:space:]]*$//g"); then
      echo "[Error] Failed to retrieve the current timezone." >&2
      exitCode=1
    fi

    echo "### Current timedatectl Settings ###"
    echo "Timezone: $currentTimeZone"

    if ! currentConfig=$(systemd-analyze cat-config systemd/timesyncd.conf --no-pager); then
      echo "[Error] Failed to retrieve the current time settings." >&2
      exitCode=1
    fi
    echo "$currentConfig" | awk '/^# \/.*\.conf/ { print; next } /^\s*#/ { next } { print }'

    echo ""

    echo "### Current Time ###"
    if ! date "+%x %r"; then
      echo "[Error] Failed to retrieve the current time." >&2
      exitCode=1
    fi

    exit "$exitCode"
  fi
fi

# Check if a primary sync server is specified
if [[ -n $primarySyncServer ]]; then
  # Retrieve the current primary sync server configuration
  currentPrimarySyncServer=$(grep -w -r -H "^NTP" /etc/systemd/timesyncd.conf.d/*.conf)
  currentPrimarySyncServer=$(echo "$currentPrimarySyncServer" | grep -v '^$')
  currentPrimaryServerCount=$(echo "$currentPrimarySyncServer" | awk 'NF' | wc -l | xargs)

  # Ensure there are no duplicate primary sync server entries
  if [[ $currentPrimaryServerCount -gt 1 ]]; then
    _PRINT_HELP=no die "[Error] Multiple primary sync servers were found. Please correct this before attempting to adjust the sync servers.
$currentPrimarySyncServer" 1
  fi

  # Update the primary sync server if necessary
  if [[ -n $currentPrimarySyncServer ]]; then
    if ! echo "$currentPrimarySyncServer" | grep -w "$primarySyncServer" 1> /dev/null 2> /dev/null; then
      currentPrimaryValue=$(echo "$currentPrimarySyncServer" | awk -F "=" '{ print $2 }')

      echo "Updating the primary sync server from '$currentPrimaryValue' to '$primarySyncServer'."
      filePath=${currentPrimarySyncServer//:*/}
      timestamp=$(date "+%s")
      updatedFilePath="/etc/systemd/timesyncd.conf.d/$timestamp-ntp.conf"

      # Save the updated configuration file
      echo "Saving the updated configuration file to '$updatedFilePath'."
      sed "s/^NTP=.*/NTP=$primarySyncServer/g" "$filePath" > "$updatedFilePath"

      # Validate the creation of the updated file
      if [[ ! -s $updatedFilePath ]]; then
        _PRINT_HELP=no die "[Error] Failed to create the file '$updatedFilePath'. This is needed to adjust the sync servers." 1
      fi

      # Backup the old configuration file
      echo "Backing up the old configuration file to '$filePath.old'."
      if ! mv "$filePath" "$filePath.old"; then
        _PRINT_HELP=no die "[Error] Failed to remove the old config file at '$filePath'. This is needed to adjust the sync servers." 1
      fi

      echo "Successfully updated the primary sync server."
    else
      echo "The primary NTP server is already set to '$primarySyncServer'."
    fi
  fi

  # Create a new configuration file if no primary sync server exists
  if [[ -z $currentPrimarySyncServer ]]; then
    echo "Setting the primary sync server to '$primarySyncServer'."
    timestamp=$(date "+%s")
    ntpPrimaryFilePath="/etc/systemd/timesyncd.conf.d/$timestamp-ntp-primary-server.conf"
    echo "Creating configuration file at '$ntpPrimaryFilePath'."

    # Write the new configuration file
    {
      echo "[Time]"
      echo "NTP=$primarySyncServer"
      echo "#FallbackNTP=ntp.ubuntu.com"
      echo "#RootDistanceMaxSec=5"
      echo "#PollIntervalMinSec=32"
      echo "#PollIntervalMaxSec=2048"
      echo "#ConnectionRetrySec=30"
      echo "#SaveIntervalSec=60"
    } > "$ntpPrimaryFilePath"

    # Validate the creation of the new file
    if [[ ! -s $ntpPrimaryFilePath ]]; then
      _PRINT_HELP=no die "[Error] Failed to create the file '$ntpPrimaryFilePath'. This is needed to adjust the sync servers." 1
    fi

    echo "Successfully set the primary sync server."
  fi

  # Update the list of configuration files and mark the need to restart timedatectl
  timeSyncConfigFiles=$(ls /etc/systemd/timesyncd.conf.d/*.conf 2> /dev/null)
  needToRestartTimedatectl="yes"
  echo ""
  sleep 1
fi

# Check if a fallback sync server is specified
if [[ -n $fallbackSyncServer ]]; then
  # Retrieve the current fallback sync server configuration
  currentFallbackSyncServer=$(grep -w -r -H "^FallbackNTP" /etc/systemd/timesyncd.conf.d/*.conf)
  currentFallbackSyncServer=$(echo "$currentFallbackSyncServer" | grep -v '^$')
  currentFallbackServerCount=$(echo "$currentFallbackSyncServer" | awk 'NF' | wc -l | xargs)

  # Ensure there are no duplicate fallback sync server entries
  if [[ $currentFallbackServerCount -gt 1 ]]; then
    _PRINT_HELP=no die "[Error] Multiple fallback sync servers were found. Please correct this before attempting to adjust the sync servers.
$currentPrimarySyncServer" 1
  fi

  # Update the fallback sync server if necessary
  if [[ -n $currentFallbackSyncServer ]]; then
    if ! echo "$currentFallbackSyncServer" | grep -w "$fallbackSyncServer" 1> /dev/null 2> /dev/null; then
      currentFallbackValue=$(echo "$currentFallbackSyncServer" | awk -F "=" '{ print $2 }')

      echo "Updating the fallback sync server from '$currentFallbackValue' to '$fallbackSyncServer'."
      filePath=${currentFallbackSyncServer//:*/}
      timestamp=$(date "+%s")
      updatedFilePath="/etc/systemd/timesyncd.conf.d/$timestamp-ntp.conf"

      # Save the updated configuration file
      echo "Saving the updated configuration file to '$updatedFilePath'."
      sed "s/^FallbackNTP=.*/FallbackNTP=$fallbackSyncServer/g" "$filePath" > "$updatedFilePath"

      # Validate the creation of the updated file
      if [[ ! -s $updatedFilePath ]]; then
        _PRINT_HELP=no die "[Error] Failed to create the file '$updatedFilePath'. This is needed to adjust the sync servers." 1
      fi

      # Backup the old configuration file
      echo "Backing up the old configuration file to '$filePath.old'."
      if ! mv "$filePath" "$filePath.old"; then
        _PRINT_HELP=no die "[Error] Failed to remove the old config file at '$filePath'. This is needed to adjust the sync servers." 1
      fi

      echo "Successfully updated the fallback server."
    else
      echo "The fallback NTP server is already set to '$fallbackSyncServer'."
    fi
  fi

  # Create a new configuration file if no fallback sync server exists
  if [[ -z $currentFallbackSyncServer ]]; then
    echo "Setting the fallback sync server to '$fallbackSyncServer'."
    timestamp=$(date "+%s")
    ntpFallbackFilePath="/etc/systemd/timesyncd.conf.d/$timestamp-ntp-fallback-server.conf"

    echo "Creating new configuration file at '$ntpFallbackFilePath'."
    {
      echo "[Time]"
      echo "#NTP="
      echo "FallbackNTP=$fallbackSyncServer"
      echo "#RootDistanceMaxSec=5"
      echo "#PollIntervalMinSec=32"
      echo "#PollIntervalMaxSec=2048"
      echo "#ConnectionRetrySec=30"
      echo "#SaveIntervalSec=60"
    } > "$ntpFallbackFilePath"

    # Validate the creation of the new file
    if [[ ! -s $ntpFallbackFilePath ]]; then
      _PRINT_HELP=no die "[Error] Failed to create the file '$ntpFallbackFilePath'. This is needed to adjust the sync servers." 1
    fi

    echo "Successfully set the fallback sync server."
  fi

  # Update the list of configuration files and mark the need to restart timedatectl
  timeSyncConfigFiles=$(ls /etc/systemd/timesyncd.conf.d/*.conf 2> /dev/null)
  needToRestartTimedatectl="yes"
  echo ""
  sleep 1
fi

# Check if a minimum sync interval is specified
if [[ -n $_arg_syncIntervalMinimumInSeconds ]]; then
  # Retrieve the current minimum and maximum sync interval configurations
  currentMinimumSyncInterval=$(grep -w -r -H "^PollIntervalMinSec" /etc/systemd/timesyncd.conf.d/*.conf)
  currentMinimumSyncInterval=$(echo "$currentMinimumSyncInterval" | grep -v '^$')
  currentMinimumSyncIntervalCount=$(echo "$currentMinimumSyncInterval" | awk 'NF' | wc -l | xargs)

  currentMaximumSyncInterval=$(grep -w -r -H "^PollIntervalMaxSec" /etc/systemd/timesyncd.conf.d/*.conf)
  currentMaximumSyncInterval=$(echo "$currentMaximumSyncInterval" | grep -v '^$')
  currentMaximumSyncIntervalCount=$(echo "$currentMaximumSyncInterval" | awk 'NF' | wc -l | xargs)

  # Ensure there are no duplicate minimum or maximum sync interval entries
  if [[ $currentMinimumSyncIntervalCount -gt 1 ]]; then
    _PRINT_HELP=no die "[Error] Multiple minimum sync intervals were found. Please correct this before attempting to adjust the minimum sync interval.
$currentMinimumSyncInterval" 1
  fi

  if [[ $currentMaximumSyncIntervalCount -gt 1 ]]; then
    _PRINT_HELP=no die "[Error] Multiple maximum sync intervals were found. Please correct this before attempting to adjust the minimum sync interval.
$currentMaximumSyncInterval" 1
  fi

  # Validate the relationship between minimum and maximum sync intervals
  if [[ -n $currentMaximumSyncInterval && -z $_arg_syncIntervalMaximumInSeconds ]]; then
    currentMaxValue=$(echo "$currentMaximumSyncInterval" | awk -F "=" '{ print $2 }')

    if [[ currentMaxValue -lt $_arg_syncIntervalMinimumInSeconds ]]; then
      _PRINT_HELP=yes die "[Error] The maximum sync interval '$_arg_syncIntervalMaximumInSeconds' is less than the minimum sync interval '$_arg_syncIntervalMinimumInSeconds'. The minimum sync interval must be less than the max sync interval." 1
    fi
  fi

  # Update the minimum sync interval if necessary
  if [[ -n $currentMinimumSyncInterval ]]; then
    if ! echo "$currentMinimumSyncInterval" | grep -w "$_arg_syncIntervalMinimumInSeconds" 1> /dev/null 2> /dev/null; then
      currentSyncValue=$(echo "$_arg_syncIntervalMinimumInSeconds" | awk -F "=" '{ print $2 }')

      echo "Updating the minimum sync interval from '$currentSyncValue' to '$_arg_syncIntervalMinimumInSeconds' seconds."
      filePath=${currentMinimumSyncInterval//:*/}
      timestamp=$(date "+%s")
      updatedFilePath="/etc/systemd/timesyncd.conf.d/$timestamp-minimum-syncinterval.conf"

      # Save the updated configuration file
      echo "Saving the updated configuration file to '$updatedFilePath'."
      sed "s/^PollIntervalMinSec=.*/PollIntervalMinSec=$_arg_syncIntervalMinimumInSeconds/g" "$filePath" > "$updatedFilePath"

      # Validate the creation of the updated file
      if [[ ! -s $updatedFilePath ]]; then
        _PRINT_HELP=no die "[Error] Failed to create the file '$updatedFilePath'. This is needed to adjust the minimum sync interval." 1
      fi

      # Backup the old configuration file
      echo "Backing up the old configuration file to '$filePath.old'."
      if ! mv "$filePath" "$filePath.old"; then
        _PRINT_HELP=no die "[Error] Failed to remove the old config file at '$filePath'. This is needed to adjust the minimum sync interval." 1
      fi

      echo "Successfully updated the minimum sync interval."
    else
      echo "The current minimum sync interval is already set to '$_arg_syncIntervalMinimumInSeconds' seconds."
    fi
  fi

  # Create a new configuration file if no minimum sync interval exists
  if [[ -z $currentMinimumSyncInterval ]]; then
    echo "Setting the minimum sync interval to '$_arg_syncIntervalMinimumInSeconds'."
    timestamp=$(date "+%s")
    minIntervalFilePath="/etc/systemd/timesyncd.conf.d/$timestamp-minimum-syncinterval.conf"

    echo "Creating the configuration file at '$minIntervalFilePath'."
    {
      echo "[Time]"
      echo "#NTP="
      echo "#FallbackNTP=ntp.ubuntu.com"
      echo "#RootDistanceMaxSec=5"
      echo "PollIntervalMinSec=$_arg_syncIntervalMinimumInSeconds"
      echo "#PollIntervalMaxSec=2048"
      echo "#ConnectionRetrySec=30"
      echo "#SaveIntervalSec=60"
    } > "$minIntervalFilePath"

    # Validate the creation of the new file
    if [[ ! -s $minIntervalFilePath ]]; then
      _PRINT_HELP=no die "[Error] Failed to create the file '$minIntervalFilePath'. This is needed to adjust the minimum sync interval." 1
    fi

    echo "Successfully set the minimum sync interval."
  fi

  # Update the list of configuration files and mark the need to restart timedatectl
  timeSyncConfigFiles=$(ls /etc/systemd/timesyncd.conf.d/*.conf 2> /dev/null)
  needToRestartTimedatectl="yes"
  echo ""
  sleep 1
fi

# Check if the maximum sync interval argument is provided
if [[ -n $_arg_syncIntervalMaximumInSeconds ]]; then
  # Retrieve the current maximum sync interval configuration
  currentMaximumSyncInterval=$(grep -w -r -H "^PollIntervalMaxSec" /etc/systemd/timesyncd.conf.d/*.conf)
  currentMaximumSyncInterval=$(echo "$currentMaximumSyncInterval" | grep -v '^$')
  currentMaximumSyncIntervalCount=$(echo "$currentMaximumSyncInterval" | awk 'NF' | wc -l | xargs)

  # Retrieve the current minimum sync interval configuration
  currentMinimumSyncInterval=$(grep -w -r -H "^PollIntervalMinSec" /etc/systemd/timesyncd.conf.d/*.conf)
  currentMinimumSyncInterval=$(echo "$currentMinimumSyncInterval" | grep -v '^$')
  currentMinimumSyncIntervalCount=$(echo "$currentMinimumSyncInterval" | awk 'NF' | wc -l | xargs)

  # Ensure there are no duplicate maximum sync interval entries
  if [[ $currentMaximumSyncIntervalCount -gt 1 ]]; then
    _PRINT_HELP=no die "[Error] Multiple maximum sync intervals were found. Please correct this before attempting to adjust the maximum sync interval.
$currentMaximumSyncInterval" 1
  fi

  # Ensure there are no duplicate minimum sync interval entries
  if [[ $currentMinimumSyncIntervalCount -gt 1 ]]; then
    _PRINT_HELP=no die "[Error] Multiple minimum sync intervals were found. Please correct this before attempting to adjust the maximum sync interval.
$currentMinimumSyncInterval" 1
  fi

  # Validate the relationship between minimum and maximum sync intervals
  if [[ -n $currentMinimumSyncInterval && -z $_arg_syncIntervalMinimumInSeconds ]]; then
    currentMinValue=$(echo "$currentMinimumSyncInterval" | awk -F "=" '{ print $2 }')

    if [[ currentMinValue -gt $_arg_syncIntervalMaximumInSeconds ]]; then
      _PRINT_HELP=yes die "[Error] The maximum sync interval '$_arg_syncIntervalMaximumInSeconds' is less than the minimum sync interval '$_arg_syncIntervalMinimumInSeconds'. The minimum sync interval must be less than the max sync interval." 1
    fi
  fi

  # Update the maximum sync interval if necessary
  if [[ -n $currentMaximumSyncInterval ]]; then
    if ! echo "$currentMaximumSyncInterval" | grep -w "$_arg_syncIntervalMaximumInSeconds" 1> /dev/null 2> /dev/null; then
      currentSyncValue=$(echo "$_arg_syncIntervalMaximumInSeconds" | awk -F "=" '{ print $2 }')

      echo "Updating the maximum sync interval from '$currentSyncValue' to '$_arg_syncIntervalMaximumInSeconds' seconds."
      filePath=${currentMaximumSyncInterval//:*/}
      timestamp=$(date "+%s")
      updatedFilePath="/etc/systemd/timesyncd.conf.d/$timestamp-maximum-syncinterval.conf"

      # Save the updated configuration file
      echo "Saving the updated configuration file to '$updatedFilePath'."
      sed "s/^PollIntervalMaxSec=.*/PollIntervalMaxSec=$_arg_syncIntervalMaximumInSeconds/g" "$filePath" > "$updatedFilePath"

      # Validate the creation of the updated file
      if [[ ! -s $updatedFilePath ]]; then
        _PRINT_HELP=no die "[Error] Failed to create the file '$updatedFilePath'. This is needed to adjust the maximum sync interval." 1
      fi

      # Backup the old configuration file
      echo "Backing up the old configuration file to '$filePath.old'."
      if ! mv "$filePath" "$filePath.old"; then
        _PRINT_HELP=no die "[Error] Failed to remove the old config file at '$filePath'. This is needed to adjust the maximum sync interval." 1
      fi

      echo "Successfully updated the maximum sync interval."
    else
      echo "The current maximum sync interval is already set to '$_arg_syncIntervalMaximumInSeconds' seconds."
    fi
  fi

  # Create a new configuration file if no maximum sync interval exists
  if [[ -z $currentMaximumSyncInterval ]]; then
    echo "Setting the maximum sync interval to '$_arg_syncIntervalMaximumInSeconds'."
    timestamp=$(date "+%s")
    maxIntervalFilePath="/etc/systemd/timesyncd.conf.d/$timestamp-maximum-syncinterval.conf"

    echo "Creating the configuration file at '$maxIntervalFilePath'."
    {
      echo "[Time]"
      echo "#NTP="
      echo "#FallbackNTP=ntp.ubuntu.com"
      echo "#RootDistanceMaxSec=5"
      echo "#PollIntervalMinSec=32"
      echo "PollIntervalMaxSec=$_arg_syncIntervalMaximumInSeconds"
      echo "#ConnectionRetrySec=30"
      echo "#SaveIntervalSec=60"
    } > "$maxIntervalFilePath"

    # Validate the creation of the new file
    if [[ ! -s $maxIntervalFilePath ]]; then
      _PRINT_HELP=no die "[Error] Failed to create the file '$maxIntervalFilePath'. This is needed to adjust the maximum sync interval." 1
    fi

    echo "Successfully set the maximum sync interval."
  fi

  # Update the list of configuration files and mark the need to restart timedatectl
  timeSyncConfigFiles=$(ls /etc/systemd/timesyncd.conf.d/*.conf 2> /dev/null)
  needToRestartTimedatectl="yes"
  echo ""
  sleep 1
fi

# Restart timedatectl if necessary
if [[ $needToRestartTimedatectl == "yes" ]]; then
  # Enable NTP if it is currently disabled
  if timedatectl show | grep -w "NTP" | grep "no" 1> /dev/null; then
    echo "Turning on NTP."
    if ! timedatectl set-ntp true; then
      _PRINT_HELP=no die "[Error] Failed to turn on NTP." 1
    fi
  fi

  # Restart the systemd-timesyncd service to apply changes
  if ! systemctl daemon-reload; then
    _PRINT_HELP=no die "[Error] Failed to run 'systemctl daemon-reload'." 1
  fi

  if ! systemctl restart systemd-timesyncd; then
    _PRINT_HELP=no die "[Error] Failed to restart 'systemd-timesyncd'." 1
  fi
fi

echo "### Previous timedatectl Settings ###"
echo "Timezone: $previousTimeZone"
echo "$previousTimeSettings"

echo ""

if ! currentTimeZone=$(timedatectl show | grep "Timezone=" | sed "s/Timezone=//" | sed "s/^[[:space:]]*//g" | sed "s/[[:space:]]*$//g"); then
  echo "[Error] Failed to retrieve the current timezone." >&2
  exitCode=1
fi

echo "### Current timedatectl Settings ###"
echo "Timezone: $currentTimeZone"
if ! currentConfig=$(systemd-analyze cat-config systemd/timesyncd.conf --no-pager); then
  echo "[Error] Failed to retrieve the current time settings." >&2
  exitCode=1
fi
echo "$currentConfig" | awk '/^# \/.*\.conf/ { print; next } /^\s*#/ { next } { print }'

echo ""

echo "### Current Time ###"
if ! date "+%x %r"; then
  echo "[Error] Failed to retrieve the current time." >&2
  exitCode=1
fi

exit "$exitCode"

 

Detailed Breakdown

Here’s what the script does, step by step.

  1. Argument parsing and help
    • Supports:
      –listTimeZones|-l
      –setTimeZone|-t <tz>
      –setSyncServers|-s <server[,server]>
      –syncIntervalMinimumInSeconds|–min <sec>
      –syncIntervalMaximumInSeconds|–max <sec>
    • Shows a concise usage menu and validates combinations (e.g., you can’t use –listTimeZones with other options).
  2. Environment and prerequisites
    • Requires root (id -u check).
    • Requires timedatectl and systemd-timesyncd. If systemd-timesyncd is disabled, it exits with guidance.
    • If NTP-related options are used, verifies the host supports NTP via timedatectl show | CanNTP=.
  3. Input validation
    • Time zone: validates against timedatectl list-timezones.
    • NTP servers: accepts up to two, allows only safe characters, and live-checks UDP/123 reachability using a /dev/udp probe with a timeout.
    • Intervals: numeric, 1–86400 seconds, and ensures min ≤ max.
  4. Discovery of current state
    • Gathers the effective timesyncd configuration with systemd-analyze cat-config systemd/timesyncd.conf, strips comments, and stores a “previous settings” snapshot for before/after reporting.
  5. Time zone changes
    • If requested, calls timedatectl set-timezone <tz> and confirms the result. If already set, it reports that and moves on.
  6. Configuration layering
    • Uses /etc/systemd/timesyncd.conf.d/ drop-ins instead of editing /etc/systemd/timesyncd.conf in place.
    • If the default file exists and differs from desired state, marks that an update is required, then writes a new, timestamped drop-in, e.g., /etc/systemd/timesyncd.conf.d/1752702365-ntp.conf.
  7. Selective updates
    • Updates primary NTPfallback NTPPollIntervalMinSec, and PollIntervalMaxSec individually if they exist; otherwise creates specific drop-ins for each.
    • When updating, it writes a new file, then backs up the old one as .old, avoiding fragile in-place edits.
  8. Apply and report
    • Ensures set-ntp true if NTP was disabled.
    • Runs systemctl daemon-reload && systemctl restart systemd-timesyncd.
    • Prints a before/after configuration diff-style view and the current time, so you have immediate confirmation.

Potential Use Cases

Case study: An MSP onboards a 500-node manufacturing client across three plants. Devices were imaged with a generic UTC zone and inconsistent NTP. Kerberos tickets and TLS validation intermittently fail. The engineer pushes this shell script to set the time zone in Linux and NTP timedatectl settings via their RMM with per-site parameters:

  • Site A: –setTimeZone “America/Chicago” –setSyncServers “0.pool.ntp.org,1.pool.ntp.org” –min 32 –max 2048
  • Site B uses a corporate NTP pair; Site C uses regional pool servers.

Within minutes, authentication failures disappear and SIEM correlation is clean.

Comparisons

  • systemd-timesyncd vs chrony: chrony is feature-rich and popular for servers needing advanced controls (slew rates, sources, statistics). For endpoints and many servers, systemd-timesyncd is lightweight and “good enough,” especially when standardized with timedatectl.
  • Editing /etc/localtime manually vs timedatectl set-timezone: Direct symlink edits work but are brittle at scale; timedatectl is declarative and auditable.
  • Editing /etc/systemd/timesyncd.conf directly vs drop-ins: Drop-ins are safer, survive package updates, and are easier to diff/rollback—this script follows best practice.

Implications for Security and Reliability

Correct time underpins KerberosJWT/SSO token validitycertificate verification, and log correlation. Misaligned clocks create false positives in SIEMs, fail compliance checks, and weaken forensic timelines. Standardizing NTP, PollIntervalMinSec, and PollIntervalMaxSec reduces drift and speeds convergence after outages.

Recommendations

  • Parameterize by site or tenant: Keep time zones and NTP servers aligned with geography and policy.
  • Use internal NTP first: Prefer corporate stratum servers; fall back to pool servers.
  • Keep intervals sane: Defaults (32–2048 seconds) are reasonable for most environments; tighten only with a clear need.
  • Document and store artifacts: Retain the script’s before/after outputs in your CMDB or ticket.
  • Run as root in maintenance windows: Restarting systemd-timesyncd is low risk but still a service change.
  • Monitor: After rollout, verify timedatectl show across a sample to confirm NTP=yes and correct peers.

Final Thoughts

For IT teams standardizing Linux estates, this shell script to set the time zone and NTP timedatectl settings in Linuxoffers an auditable, idempotent approach that plays nicely with modern distros. Paired with NinjaOne, you can deploy it as a script policy, feed site-specific parameters through Custom Fields, schedule periodic compliance checks, and alert on drift. The result is predictable time across your fleet—and fewer mysteries in your logs.

FAQs

No. The script requires systemd, systemd-timesyncd, and timedatectl.

The script intentionally caps at two to avoid noisy configurations. You can adjust the validation if your policy differs.

The script will fail fast on the reachability check. Permit NTP, use an internal NTP relay, or configure allowed egress.

It avoids in-place edits; when it updates, it writes a new timestamped file and moves the prior file to .old.

The script prints “Previous” and “Current” settings and timestamps every generated file for traceability.

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service delivery tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Categories:

You might also like