Automatically get Network Time Server

Jason
Contributor II

I know in Windows, once a system is domain joined it automatically gets time information from the Domain Controller (no policies or scripts need to be run to do this).

For OS X I've bound Mavericks systems to our AD, but they still seem to get network time from time.apple.com, which fails because port 123 outbound is blocked.

After binding Mavericks to AD, shouldn't change it's time server from time.apple.com to whichever DC was used for authentication? Or must i run some script or policy to manually tell it to look internally for the time?

I know that sudo systemsetup -setnetworktimeserver "SOMESERVER" should do the trick, but i'd rather not set it statically since the DC might change depending on where the system is.

21 REPLIES 21

bvrooman
Valued Contributor

OS X doesn't automatically change NTP servers. You can point it to one using systemsetup as you described, and then add alternates like this:

echo "server 12.34.56.78" >> /etc/ntp.conf

alexjdale
Valued Contributor III

You can set your domain as the time server (FQDN, such as domain.example.com) and it will use the domain controller it's already talking to.

azbikowski
New Contributor II

I've got a JAMF created script in my JSS for setting the time server. I don't recall if it was bundled in to Casper or if I pulled it off JAMF Nation.

#!/bin/sh
####################################################################################################
#
# Copyright (c) 2010, JAMF Software, LLC.  All rights reserved.
#
#       Redistribution and use in source and binary forms, with or without
#       modification, are permitted provided that the following conditions are met:
#               * Redistributions of source code must retain the above copyright
#                 notice, this list of conditions and the following disclaimer.
#               * Redistributions in binary form must reproduce the above copyright
#                 notice, this list of conditions and the following disclaimer in the
#                 documentation and/or other materials provided with the distribution.
#               * Neither the name of the JAMF Software, LLC nor the
#                 names of its contributors may be used to endorse or promote products
#                 derived from this software without specific prior written permission.
#
#       THIS SOFTWARE IS PROVIDED BY JAMF SOFTWARE, LLC "AS IS" AND ANY
#       EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#       WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#       DISCLAIMED. IN NO EVENT SHALL JAMF SOFTWARE, LLC BE LIABLE FOR ANY
#       DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#       (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#       LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#       ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#       SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
####################################################################################################
#
# SUPPORT FOR THIS PROGRAM
#
#       This program is distributed "as is" by JAMF Software, LLC's Resource Kit team. For more
#       information or support for the Resource Kit, please utilize the following resources:
#
#               http://list.jamfsoftware.com/mailman/listinfo/resourcekit
#
#               http://www.jamfsoftware.com/support/resource-kit
#
#       Please reference our SLA for information regarding support of this application:
#
#               http://www.jamfsoftware.com/support/resource-kit-sla
#
####################################################################################################
#
# ABOUT THIS PROGRAM
#
# NAME
#   setTimeServers.sh -- Set a time server.
#
# SYNOPSIS
#   sudo setTimeServer.sh
#   sudo setTimeServer.sh <mountPoint> <computerName> <currentUsername> <timeServer>
#
# DESCRIPTION
#   This script will set a Time Server in the network settings for whichever network interface has
#   been specified.
#
####################################################################################################
#
# HISTORY
#
#   Version: 1.0
#
#   - Created by Tedd Herman on December 29,2008
#
####################################################################################################
#
# DEFINE VARIABLES & READ IN PARAMETERS
#
####################################################################################################


# HARDCODED VALUES ARE SET HERE
timeServer=""

# CHECK TO SEE IF A VALUE WAS PASSED IN PARAMETER 4 AND, IF SO, ASSIGN TO "timeServer"
if [ "$4" != "" ] && [ "$timeServer" == "" ];then
    timeServer=$4
fi

####################################################################################################
# 
# SCRIPT CONTENTS - DO NOT MODIFY BELOW THIS LINE
#
####################################################################################################

OS=`/usr/bin/defaults read /System/Library/CoreServices/SystemVersion ProductVersion | awk '{print substr($1,1,4)}'`

if [ "$timeServer" != "" ]; then
    if [[ "$OS" < "10.5" ]]; then
        echo "Setting network time server to: $timeServer..."
        /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support/systemsetup -setnetworktimeserver $timeServer
        /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support/systemsetup -setusingnetworktime on
    else
        echo "Setting network time server to: $timeServer..."
        /usr/sbin/systemsetup -setnetworktimeserver $timeServer
        /usr/sbin/systemsetup -setusingnetworktime on
    fi
else
    echo "Error:  The parameter 'timeServer' is blank.  Please specify a time server."
fi

Then I have an extension attribute for getting the current value:

#!/bin/sh
OS=`/usr/bin/sw_vers -productVersion | /usr/bin/colrm 5`
if [[ "$OS" < "10.5" ]]; then
if [ -f /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support/systemsetup ];then      
    echo "<result>`/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support/systemsetup -getnetworktimeserver | awk '{print $4}'`</result>"
else
    echo "<result>The systemsetup binary is not present on this machine.</result>"
fi
else
    echo "<result>`/usr/sbin/systemsetup -getnetworktimeserver | awk '{print $4}'`</result>"
fi

From there, just scoped a policy to modify the time server as needed.

znilsson
Contributor II

In my case I just wrote a simple script to tell it to use our internal time server.

systemsetup -setusingnetworktime on -setnetworktimeserver **nameoftimeserver**

Works like a charm for us. I just have that script set to run when enrollment is complete, and once per computer.

Jason
Contributor II

Thanks, I should of known i could of just pointed setnetworktimeserver to the domain name and it'd work.

Are you guys also setting time zone? I'm getting "Unable to determine current location at this time" on the Time Zone screen. Wireshark traces look like it's trying to connect to "gs-loc.ls-apple.com.akadns.net" over port 443, and if that's all it's using for location services it'd make sense that would fail as 443 is also blocked. Are you seeing the same? If so, i'm assuming i'll need to set it manually using systemsetup -settimezone <TIMEZONE>.

robertal
New Contributor

I think there's a bug in this script post OSX 10.10. This line

if [[ "$OS" < "10.5" ]]; then

causes problems if you are on OS 10.10 or better, as string 10.10 and 10.11 are lexicographically less than 10.5, causing the wrong path to run. I could see this in my policy logs when I tried to run it.

I believe if you change it to

if [[ "$OS" < "$10.5" ]]; then

you'll get a correct numeric to numeric comparison that will work better. I tested this on my 10.11 machine and it works well from what I can tell.

MarcosMunoz
New Contributor III

We have several sites and some are in different time zones. How would I set the time server according to network subnet?

Thanks.

Nix4Life
Valued Contributor

@mmunoz2

you would have to bake logic into the script based on timeserver and subnet. An if-then-else loop

Larry

Swift
New Contributor II

You might want to check if your DHCP is advertising the NTP service (Option_42)
Something like this...

#!/bin/sh
IPv4PrimaryService=$(echo "show State:/Network/Global/IPv4" | scutil | grep "PrimaryService" | cut -d":" -f 2- | sed "s|^[ ]*||;s|[ ]*$||")
echo "show State:/Network/Service/${IPv4PrimaryService}/DHCP" | scutil | grep "Option_"

sean
Valued Contributor

@Jason

I don't think it matters which DC it picks time from, it's time zone that differs, so as long as timezone is correct it should work it out; reference time is the same globally. Eg. If I changed my time server to time.asia.apple.com I shouldn't suddenly get some time from a random location in Asia, I should still get time for my Time Zone.

We script it, using as you suggested:

systemsetup -settimezone <TIMEZONE>

As @bvrooman suggested, consider multiple time servers. If the battery runs dead and you end up with incorrect time, depending upon configuration, users may not be able to correct the time and the machine won't be able to correct itself if the time server can't be contacted, e.g. a laptop off site that is configured to sync with an internal time server.

@Swift If you know which port is in use, e.g. en0, you could query option 42 directly.

ipconfig getoption en0 dhcp_network_time_protocol_servers

dhcp options listed in the bootp man page

@mmunoz2 Depending upon how you have your AD configured, you may be able to get location info from AD. Look inside

/Library/Preferences/OpenDirectory/DynamicData/Active Directory/

You should find a plist. If sites are configured, try reading the sitename.

/usr/libexec/PlistBuddy -c "Print :ActiveDirectory:sitename " /Library/Preferences/OpenDirectory/DynamicData/Active Directory/[YOUR FILE].plist

AD Sites and Services

@azbikowski @robertal

If you wish to compare versions, comparing each part of the version independently should be reliable.

Eg.

#!/bin/bash

major_version=`sw_vers -productVersion | cut -d "." -f 1`
first_minor_version=`sw_vers -productVersion | cut -d "." -f 2`
# second_minor_version=`sw_vers -productVersion | cut -d "." -f 3`

if [ $major_version -eq 10 ]
then
        if [ $first_minor_version -gt 5 ]
        then
                SystemSetup="/usr/sbin/systemsetup"
        else
                SystemSetup="/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support/systemsetup"
        fi
fi

$SystemSetup -getnetworktimeserver

exit 0

However, based on the fact that there are only two options, you could just do:

#!/bin/bash

SystemSetup="/usr/sbin/systemsetup"

if [ ! -e $SystemSetup ]
then
        SystemSetup="/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support/systemsetup"
fi

$SystemSetup -getnetworktimeserver

exit 0

brock_walters
Contributor

Hi guys -

Just wanted to point out that the version of the setTimeServers.sh script posted in the thread above is old & has been updated:

setTimeServers.sh

Try downloading our scripts before using older versions. We have fixed many of the scripts that are commonly used including this one. Also, if there are assets here you use that you'd like to see updated, let us know. Thanks!

donmontalvo
Esteemed Contributor III

Might want to bounce ntpd after changing /etc/ntp.conf?

/bin/launchctl unload /System/Library/LaunchDaemons/org.ntp.ntpd.plist
/bin/sleep 2
/bin/launchctl load /System/Library/LaunchDaemons/org.ntp.ntpd.plist
--
https://donmontalvo.com

leslie
Contributor II
Contributor II

I like setting multiple time servers, one internal and one external. Perhaps something like the following might get you on track.

#!/bin/bash

## turn off network time
systemsetup -setusingnetworktime off

## set global time servers
global_timeserver="0.north-america.pool.ntp.org"

## get subnet, returns something like 10.10.4
local_subnet=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*.){3}[0-9]*' | grep -Eo '([0-9]*.){3}[0-9]*' | grep -v '127.0.0.1' | cut -f1-3 -d.)

case $local_subnet in
    10.10.4)
        local_timeserver="10.10.4.11"
            ;;
    10.10.5)
        local_timeserver="10.10.5.11"
            ;;
    *)
        ## most reliable DC
        local_timeserver="10.10.2.11"
            ;;
esac

## in case ntp.conf file doesn't exist, create it
touch /private/etc/ntp.conf

## save current ntp.conf file
mv /private/etc/ntp.conf /private/etc/ntp.conf.orig

## create new file
echo "server $local_timeserver" > /private/etc/ntp.conf
echo "server $global_timeserver" >> /private/etc/ntp.conf

## reenable network time
systemsetup -setusingnetworktime on

sean
Valued Contributor

@brock.walters You might want to put an exit 0 at the end of your script.

sean
Valued Contributor

+1 for @leslie and multiple time servers. We actually use systemsetup to set the first time server and then add extra with an echo. As the systemsetup command will only allow one entry, you know that you will only have one entry after running the command (essentially cleaning the file for you or creating it if it doesn't exist).

Something like:

systemsetup -setnetworktimeserver $local_timeserver
echo "server $global_timeserver" >> /etc/ntp.conf

brock_walters
Contributor

Most well-behaved bash commands exit with a status of 0 on their own unless something is wrong. Exit codes can be built in to scripts to customize logging or halting behavior but most of the time when you see them they are unnecessary.

sean
Valued Contributor

Moot point since it won't ever get to the end of the script.

if/else block ends and then there's another else/fi and $4 is probably unique to your use.

Self Service apparently can suffer without neatly exiting a script:

Jamf Post 19614

It's good to help everyone who struggles with this, but perhaps testing may be wise if sharing scripts. At best you should expect an untested script to just error out, but worse still it could damage systems.

brock_walters
Contributor

Not sure what you mean is moot: your point about exit codes? My point isn't - most scripts don't need exit codes if they are well-formed, period, however, you can add them to modify behavior. A version of the set time server script has been available since 2008 on JAMF Nation & never had an exit 0 at the end, but, the great thing about all of the scripts you can download from JAMF Nation is that you can modify them as much or as little as you like.

sean
Valued Contributor

No, not moot about exit codes, moot that it will never reach the end of the script because the script is malformed and won't ever run successfully.

brock_walters
Contributor

Well, that's a little embarrassing... The version that is supposed to be uploaded is not. My apologies for that. We will get the script up to date but in the mean time here is what will be uploaded eventually & should be there now:

#!/bin/sh
####################################################################################################
#
# Copyright (c) 2010, JAMF Software, LLC.  All rights reserved.
#
#       Redistribution and use in source and binary forms, with or without
#       modification, are permitted provided that the following conditions are met:
#               * Redistributions of source code must retain the above copyright
#                 notice, this list of conditions and the following disclaimer.
#               * Redistributions in binary form must reproduce the above copyright
#                 notice, this list of conditions and the following disclaimer in the
#                 documentation and/or other materials provided with the distribution.
#               * Neither the name of the JAMF Software, LLC nor the
#                 names of its contributors may be used to endorse or promote products
#                 derived from this software without specific prior written permission.
#
#       THIS SOFTWARE IS PROVIDED BY JAMF SOFTWARE, LLC "AS IS" AND ANY
#       EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#       WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#       DISCLAIMED. IN NO EVENT SHALL JAMF SOFTWARE, LLC BE LIABLE FOR ANY
#       DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#       (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#       LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#       ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#       SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
####################################################################################################
#
# SUPPORT FOR THIS PROGRAM
#
#       This program is distributed "as is" by JAMF Software, LLC's Resource Kit team. For more
#       information or support for the Resource Kit, please utilize the following resources:
#
#               http://list.jamfsoftware.com/mailman/listinfo/resourcekit
#
#               http://www.jamfsoftware.com/support/resource-kit
#
#       Please reference our SLA for information regarding support of this application:
#
#               http://www.jamfsoftware.com/support/resource-kit-sla
#
####################################################################################################
#
# ABOUT THIS PROGRAM
#
# NAME
#   setTimeServers.sh -- Set a time server.
#
# SYNOPSIS
#   sudo setTimeServer.sh
#   sudo setTimeServer.sh <mountPoint> <computerName> <currentUsername> <timeServer>
#
# DESCRIPTION
#   This script will set a Time Server in the network settings for whichever network interface has
#   been specified.
#
####################################################################################################
#
# HISTORY
#
#   Version: 1.0
#
#   - Created by Tedd Herman on December 29,2008
#
#   Version 2.0
#
#   - Updated by Brock Walters Nov 8 2014
#
####################################################################################################
#
# DEFINE VARIABLES & READ IN PARAMETERS
#
####################################################################################################

# HARDCODED VALUES ARE SET HERE
timeServer=""

# CHECK TO SEE IF A VALUE WAS PASSED IN PARAMETER 4 AND, IF SO, ASSIGN TO "timeServer"
if [ "$4" != "" ] && [ "$timeServer" == "" ]
then
    timeServer=$4
fi

####################################################################################################
#
# SCRIPT CONTENTS - DO NOT MODIFY BELOW THIS LINE
#
####################################################################################################

osx=$(/usr/bin/defaults read /System/Library/CoreServices/SystemVersion ProductVersion | awk '{print $1}')
maj=$(/usr/bin/defaults read /System/Library/CoreServices/SystemVersion ProductVersion | awk '{print substr($1,1,2)}')
ref=$(/usr/bin/defaults read /System/Library/CoreServices/SystemVersion ProductVersion | awk '{print substr($1,4,2)}')

if [ $maj -gt 10 ]
then
  echo
  echo "Check OS string format & OS X systemsetup utility for script compatibility with OS X version $osx"
  echo
  exit
fi

if [ "$timeServer" != "" ]
then
    if [ $ref -lt 5 ]
    then
        echo
        echo "Setting network time server to: $timeServer..."
        /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support/systemsetup -setnetworktimeserver $timeServer
        /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support/systemsetup -setusingnetworktime on
        echo
    else
        echo
        echo "Setting network time server to: $timeServer..."
        /usr/sbin/systemsetup -setnetworktimeserver $timeServer
        /usr/sbin/systemsetup -setusingnetworktime on
        echo
    fi
else
    echo
    echo "Error:  The parameter 'timeServer' is blank.  Please specify a time server."
    echo
fi

brock_walters
Contributor

Hello - the fixed version of this script (identical to what is posted above) is now available on the JAMF Nation Scripts page for download. Thanks!