Posted on 10-03-2016 08:49 AM
Hey guys,
I am looking to get a smart group set up to notify me when Macs age out after 4 years for upgrades. I am doing this right now using the model and specifying the year they were made, but that just means every year I need to add a new field. Is there an easier way to do this?
Solved! Go to Solution.
Posted on 10-05-2016 11:04 AM
I put together an extension attribute script that gives approximate manufacture date. It is based on that part of Michael Lynn's script. GSX integration is better, of course, but has some issues for programmatically getting it for many machines as I understand (captcha and limit to number per day, unless you are a self repair shop).
#!/bin/sh
#
# Parse machine serial number for date (week and year) of manufacture
# based on pyMacWarranty by Michael Lynn (https://github.com/pudquick/pyMacWarranty)
#
# Rocky Waters - Humboldt State University - Oct 2016
#
function mnfdate()
{
local WEEK=$1 YEAR=$2
local JAN1_WEEK JAN1_DAY
local FIRST_MON
local DATE_FMT="%d %b %Y"
local DATEYEAR DAYS DAYSTMP
DATEYEAR="01-Jan-$YEAR"
JAN1_WEEK=$(date -jf "%d-%b-%Y" "$DATEYEAR" +%W)
JAN1_DAY=$(date -jf "%d-%b-%Y" "$DATEYEAR" +%u)
# If Jan 1 is Monday then use Jan 1, else calculate what date is first Monday of year
if ((JAN1_WEEK))
then
FIRST_MON=$YEAR-Jan-01
else
FIRST_MON=$YEAR-Jan-$((01 + (7 - JAN1_DAY + 1) ))
fi
(( DAYSTMP = $WEEK * 7 ))
DAYS="-v+"$DAYSTMP"d"
DATEYEAR=$(date -j -f "%Y-%b-%d" $DAYS "$FIRST_MON" +"%Y-%m-%d")
echo "$DATEYEAR"
}
SERIAL=`ioreg -c IOPlatformExpertDevice -d 2 | awk -F" '/IOPlatformSerialNumber/{print $(NF-1)}'`
if [ "${#SERIAL}" = '11' ]
then
# Old Serial number format (11 Chars) - Changed in 2010
# Year is third character in serial number
YEAR=${SERIAL:2:1}
# Key index for years
KEY_YEAR=' 3456789012'
# Strip characters from KEY_YEAR after the YEAR
IDX_YEAR="${KEY_YEAR%%$YEAR*}"
# Base year is 2000, Manufactured year is base year + position of the YEAR in the KEY_YEAR
MNF_YEAR=$((2000 + ${#IDX_YEAR}))
# Week manufactured is characters 4-5 in serial number
WEEK=${SERIAL:3:2}
# Get an approximate date manufactured given the week number and year
MNFDATEAPPROX=$(mnfdate $WEEK $MNFYEAR)
elif [ "${#SERIAL}" = '12' ]
then
# New Serial number format (12 chars)
# Key index for years: c is first half of 2010, d is second half 2010...
# goes through 2019
KEY_YEAR='cdfghjklmnpqrstvwxyz'
# Year is fourth character in serial number
YEAR=${SERIAL:3:1}
# Set YEAR to lowercase
YEAR=$(echo $YEAR| tr '[:upper:]' '[:lower:]')
# Strip characters from KEY_YEAR after the YEAR
IDX_YEAR="${KEY_YEAR%%$YEAR*}"
# Base year is 2010, Manufactured year is base year + position of the YEAR in the KEY_YEAR
# divided by 2 (each letter is half year)
MNF_YEAR=$(( 2010 + ${#IDX_YEAR} / 2))
# determine first or second half of year
HALF_YEAR=$(( ${#IDX_YEAR} % 2))
# Key index for weeks - only gives half year need to know forst or second half to calculate
KEY_WEEK="123456789cdfghjklmnpqrtvwxy"
# Week manufactured is character 5 in serial number
ALPHA_WEEK=${SERIAL:4:1}
# Set ALPHA_WEEK to lowercase
ALPHA_WEEK=$(echo $ALPHA_WEEK| tr '[:upper:]' '[:lower:]')
# Strip characters from KEY_WEEK after ALPHA_WEEK
IDX_WEEK="${KEY_WEEK%%$ALPHA_WEEK*}"
# Position of ALPHA_WEEK in KEY_WEEK
IDX_WEEK=${#IDX_WEEK}
# WEEK is the IDX_WEEK plus 26 weeks if it is the second half of the year
WEEK=$(( IDX_WEEK + ( HALF_YEAR * 26 ) ))
# Get an approximate date manufactured given the week number and year
MNFDATEAPPROX=$(mnfdate $WEEK $MNF_YEAR)
fi
echo "<result>$MNFDATEAPPROX</result>"
Posted on 10-03-2016 09:00 AM
If you're only concerned about the actual age of the Mac, you could create an EA that decodes the machine's serial number (Google will find the formula for you) to report the age.
Posted on 10-03-2016 11:17 AM
I am having issues finding the formula, all I can find is websites that will decode it for you.
Posted on 10-03-2016 11:26 AM
Munkireport has this information, I use it in conjuction with casper. It's php so perhaps you could look under the hood to get the formula:
munkireport
Posted on 10-03-2016 01:00 PM
If you look at munkireport, the function you're interested in is estimate_manufactured_date() in file munkireport-php/app/helpers/warranty_helper.php
They refer to the same MacRumors article I was thinking of you'd find with Google: Apple Tweaks Serial Number Format With New MacBook Pro
Posted on 10-05-2016 09:29 AM
I've always used the Warranty expiration, monitored by our GSX integration. Just another thought.
Posted on 10-05-2016 11:04 AM
I put together an extension attribute script that gives approximate manufacture date. It is based on that part of Michael Lynn's script. GSX integration is better, of course, but has some issues for programmatically getting it for many machines as I understand (captcha and limit to number per day, unless you are a self repair shop).
#!/bin/sh
#
# Parse machine serial number for date (week and year) of manufacture
# based on pyMacWarranty by Michael Lynn (https://github.com/pudquick/pyMacWarranty)
#
# Rocky Waters - Humboldt State University - Oct 2016
#
function mnfdate()
{
local WEEK=$1 YEAR=$2
local JAN1_WEEK JAN1_DAY
local FIRST_MON
local DATE_FMT="%d %b %Y"
local DATEYEAR DAYS DAYSTMP
DATEYEAR="01-Jan-$YEAR"
JAN1_WEEK=$(date -jf "%d-%b-%Y" "$DATEYEAR" +%W)
JAN1_DAY=$(date -jf "%d-%b-%Y" "$DATEYEAR" +%u)
# If Jan 1 is Monday then use Jan 1, else calculate what date is first Monday of year
if ((JAN1_WEEK))
then
FIRST_MON=$YEAR-Jan-01
else
FIRST_MON=$YEAR-Jan-$((01 + (7 - JAN1_DAY + 1) ))
fi
(( DAYSTMP = $WEEK * 7 ))
DAYS="-v+"$DAYSTMP"d"
DATEYEAR=$(date -j -f "%Y-%b-%d" $DAYS "$FIRST_MON" +"%Y-%m-%d")
echo "$DATEYEAR"
}
SERIAL=`ioreg -c IOPlatformExpertDevice -d 2 | awk -F" '/IOPlatformSerialNumber/{print $(NF-1)}'`
if [ "${#SERIAL}" = '11' ]
then
# Old Serial number format (11 Chars) - Changed in 2010
# Year is third character in serial number
YEAR=${SERIAL:2:1}
# Key index for years
KEY_YEAR=' 3456789012'
# Strip characters from KEY_YEAR after the YEAR
IDX_YEAR="${KEY_YEAR%%$YEAR*}"
# Base year is 2000, Manufactured year is base year + position of the YEAR in the KEY_YEAR
MNF_YEAR=$((2000 + ${#IDX_YEAR}))
# Week manufactured is characters 4-5 in serial number
WEEK=${SERIAL:3:2}
# Get an approximate date manufactured given the week number and year
MNFDATEAPPROX=$(mnfdate $WEEK $MNFYEAR)
elif [ "${#SERIAL}" = '12' ]
then
# New Serial number format (12 chars)
# Key index for years: c is first half of 2010, d is second half 2010...
# goes through 2019
KEY_YEAR='cdfghjklmnpqrstvwxyz'
# Year is fourth character in serial number
YEAR=${SERIAL:3:1}
# Set YEAR to lowercase
YEAR=$(echo $YEAR| tr '[:upper:]' '[:lower:]')
# Strip characters from KEY_YEAR after the YEAR
IDX_YEAR="${KEY_YEAR%%$YEAR*}"
# Base year is 2010, Manufactured year is base year + position of the YEAR in the KEY_YEAR
# divided by 2 (each letter is half year)
MNF_YEAR=$(( 2010 + ${#IDX_YEAR} / 2))
# determine first or second half of year
HALF_YEAR=$(( ${#IDX_YEAR} % 2))
# Key index for weeks - only gives half year need to know forst or second half to calculate
KEY_WEEK="123456789cdfghjklmnpqrtvwxy"
# Week manufactured is character 5 in serial number
ALPHA_WEEK=${SERIAL:4:1}
# Set ALPHA_WEEK to lowercase
ALPHA_WEEK=$(echo $ALPHA_WEEK| tr '[:upper:]' '[:lower:]')
# Strip characters from KEY_WEEK after ALPHA_WEEK
IDX_WEEK="${KEY_WEEK%%$ALPHA_WEEK*}"
# Position of ALPHA_WEEK in KEY_WEEK
IDX_WEEK=${#IDX_WEEK}
# WEEK is the IDX_WEEK plus 26 weeks if it is the second half of the year
WEEK=$(( IDX_WEEK + ( HALF_YEAR * 26 ) ))
# Get an approximate date manufactured given the week number and year
MNFDATEAPPROX=$(mnfdate $WEEK $MNF_YEAR)
fi
echo "<result>$MNFDATEAPPROX</result>"
Posted on 09-20-2021 12:46 PM
Can anyone confirm that this script works with BigSur. Thanks!
Posted on 10-05-2016 12:12 PM
Thanks Rocky, I will see if that works for what I need
Posted on 10-06-2016 05:07 AM
Yea, we're SSA. That said, this is a super cool EA. Nice work!
Posted on 09-10-2018 02:46 AM
I'm new to this. How do I get this attribute (which I created the extension), how do I get it into the data I want.
Posted on 09-11-2018 09:08 AM
If you have the extension attribute set up, then just set up an advanced search on it - since it is a date that is returned, you can either specify a date (before or after) or more/less than a specific number of days.
Posted on 09-28-2018 11:39 AM
I am also new to scripts and extension attributes.
I set this up as an extension attribute but when I put it into a smart group I get no results no matter how I put in the criteria, before YYYY-MM-DD or x days before. Is there some part of your script that I need to adjust for our own network?
Posted on 11-26-2018 01:52 PM
@entrata Looks like there was a small typo in Rocky's script that would return an empty result for older machines with an 11-digit serial. The last line of the 11-digit serial conditional should be changed from:
MNFDATEAPPROX=$(mnfdate $WEEK $MNFYEAR)
to:
MNFDATEAPPROX=$(mnfdate $WEEK $MNF_YEAR)
($MNF_YEAR was missing an underscore). Otherwise, this script seems solid for me. Kudos, Rocky!
Posted on 08-30-2019 11:16 AM
@Rocky 's script (with corrections from @deehar) works for me. I'm a little unclear on how weeks are calculated. Are you using the ISO 8601 standard for numbering weeks?
It seems a reasonable presumption that Apple would follow the ISO standard.
But is it a presumption? Or has Apple documented this somewhere?
(Not that it really matters if some of my dates are a week off. I'm just curious.)
Posted on 08-30-2019 01:30 PM
I'm not sure how Apple calculated the week. ISO standard would be a reasonable guess. In the Serial Number Apple uses a single character to indicate week:
KEY_WEEK="123456789cdfghjklmnpqrtvwxy"
The calculation came from Michael Lynn (https://github.com/pudquick/pyMacWarranty). I would have to do the calculations, but I believe the date that ends up being output for the first week is calculated as the first day in January to fall on a Monday.
Posted on 02-05-2020 07:31 AM
@Rocky Its seems like Apple has just started re-using the same "year identifier" character again for devices made in this decade on the 12 digit serial numbers,
So the above script now incorrectly identifies a new MacBookPro16,1 purchased last month as being made in January 2010 and not January 2020
Example of part of a real MacBookPro16,1 serial number is: C02C25
The Mac's forth character "C" can now both mean the first half of 2010 or the first half of 2020.
There doesn't seem to be any other clear identifier in the new serial number to say its a new Mac made this decade - have you see this yourself yet?
Posted on 02-05-2020 08:07 AM
Posted on 04-29-2020 03:27 AM
Thanks @Rocky, great job!
Only one simple question:
The original pyhton script pyMacWarranty by Michael Lynn calculate the week number by the line:
est_week = alpha_week.index(week) + (est_half * 26) - 1
that you in your script translate with:
WEEK=$(( IDX_WEEK + ( HALF_YEAR * 26 ) ))
so... why the -1 is disappeared?
And yes, the two scripts return slightly different results...
The final question is: what's the most correct calculation?
Thanks.
Posted on 05-09-2020 08:58 PM
Has anyone been able to get an updated EA for retrieving the manufacture date? Just instilled a policy to refresh client computers every 4 years so my Jamf smart group is not providing me with an accurate report.
Posted on 05-10-2020 08:13 PM
@fernandez.payen: So far as I'm aware, we don't need an updated EA.
@Rocky's script above works, if you make the single-line correction noted by @deehar .
Link to script: https://www.jamf.com/jamf-nation/discussions/21504/aged-out-macs#responseChild130157
Link to correction: https://www.jamf.com/jamf-nation/discussions/21504/aged-out-macs#responseChild176391
But also note that sometime in 2021, Apple will be switching to random serial numbers, so we will no longer be able to calculate manufacturer dates after that.
Posted on 05-13-2020 12:12 PM
I tried using this above but seem to be running into some issues.
Executing Policy Serial number (computer Age)
Running script Serial Number Age...
Script exit code: 0
Script result: <result>2019-04-08</result> but Per JAMF Model:
13-inch Retina MacBook Pro (Mid 2017)
So there seems to be a miss match.
Posted on 06-29-2020 10:47 PM
@stevenjklein When this EA is ran on the new 2020 Mac models, it is coming back with a 2010 manufacturer date.
Posted on 07-02-2020 01:03 PM
@fernandez.payen : The whole issue will soon be academic, as Apple has announced plans to start using random serial numbers.
I don't know why I didn't think of this earlier, but what we really need is a script to check the model identifier. (For example, MacBookPro5,5)
I'll look into creating such a script.
Posted on 04-02-2022 11:08 AM
Anything come out of this? My org is finally wanting to track our inventory and keep things more current.
Posted on 09-20-2021 12:56 PM
Can anyone confirm that this script works with BigSur?
Posted on 02-15-2022 01:42 PM
The script works; however, the serial number format has already changed for new computers to something totally random.
For existing computers, Apple started recycling the fourth character that identifies the year of manufacture. So a 2020 MacBook Pro with a SN that starts with C02D would be identified as 2010 by the script. There's no way to compensate for this.
Posted on 04-04-2022 12:04 PM
I have been trying to get this to work all morning and have failed. I have the script setup as an EA. I create a new search with the EA checked, along with some other identifiers...results are always zero. I am not sure where I am messing up.
07-07-2022 11:42 PM - edited 07-07-2022 11:43 PM
For me the dates returned stop in 2019. Any script like this for the new serial numbers? We don't have GSX to pull from.