Skip to main content

Jamf published Build a Computer Information script for your Help Desk on the Jamf Blog this morning. In that post I used the term "module" to refer to a short script snippet that can read a piece of information from a Mac and display that information as part of a dialog shown to the end user.



For example, this gets the computer name:



# Display computer name
runCommand=$( /usr/sbin/scutil --get ComputerName )
computerName="Computer Name: $runCommand"




This Jamf Nation Discussion is for anyone who's needing assistance creating additional modules and/or helping others create modules.

@talkingmoose, again many thanks.



I have done as you suggested, and it does give a result, but it shows as -152465 days!



So not quite sure what happened there, (the extension attribute shows 89).


Hello @talkingmoose I wanted to update the script for the Enable Remote Support to launch a web browser with a webex url. I can get the command to work in Terminal specifically but not with the button that you had created within the script. Any help would be greatly appreciated.



I had changed it to the following: /usr/bin/open -a "/Applications/Safari.app" 'https://mercymeetings.webex.com/mw3200/mywebex/default.do?siteurl=mercymeetings'


I forked and went in some different directions. For anyone interested, here it is...
https://github.com/themacadmin/Jamf-Scripts/blob/master/Computer%20Information.bash



Happy to answer questions on what I did differently and why.


This script is awesome. I also added in two sections for our Helpdesk.



Here will Display the Asset Tag



## Find asset tag number
##Get MacAddress
MACaddy=$( networksetup -getmacaddress en0 | awk '{print $3}' | sed 's/:/./g' )
echo "${MACaddy}"

##Get Asset Tag
runCommand=$( curl -s -k -u jssapiusername:jssapipassword https://jamfserver:8443/JSSResource/computers/macaddress/$MACaddy | xpath /computer/general/asset_tag | awk -F '[>|<]' '{print toupper($3)}' )
assetTag="Asset Tag: $runCommand"


And a way to display the Mac Model as seen in the "About This Mac" window



##Get MacModel
runCommand=$( curl -s -k -u jssapiusername:yourjssapipassword https://jamfserver:8443/JSSResource/computers/macaddress/$MACaddy | xpath /computer/hardware/model | awk -F '[>|<]' '{print ($3)}' )
macModel="Model: $runCommand"


Make sure to edit the JSS API Username and Password and the JSS Address


A couple of general notes...



If you’re going to pull multiple bits of info from the JSS’ computer record, make the API call once, and store the response in a variable or local file, then xpath out the attributes you need from that variable or file. #efficiency



If you’re running modern, supported macOS versions, you don’t have to go to Jamf for the model’s marketing (human-friendly) name. It can be derived locally. See my fork linked above for how (and if anyone can suggest how to simplify my “seds” on that one, please let me know.


@milesleacy You should be able to simplify that line to this



defaults read /System/Library/PrivateFrameworks/ServerInformation.framework/Versions/A/Resources/English.lproj/SIMachineAttributes.plist "$modelIdentifier" | awk -F'= ' '/marketingModel/{print $NF}' | sed 's/;$//;s/^"//;s/"$//;s/\\//g'


Just to note though, the names that show up in that plist don't match what shows up in the About This Mac window. They are fine for the purposes of this script, but they'll be different than what appears there in almost all cases.


@sdunbar, this is for the same user account on the same Mac?



To troubleshoot, you can add an echo statement below each of the lines in the Calculations section. This will show you the results returned for each calculation and we can see where things are not calculating correctly.



For example, change this:



lastPasswordCalc1=$(( $lastPasswordSet / 10000000 - 1644473600 ))



to this:



lastPasswordCalc1=$(( $lastPasswordSet / 10000000 - 1644473600 ))
echo "Last Password Calc 1 = $lastPasswordCalc"



Run the script again from your policy and then look at the policy logs. Are you able to see where the calculations are failing?


@mm2270



Thanks, that worked well.



I certainly haven't tested on every model, however, on all of the models I have tested, I get accurate results.



Are you aware of specific models that don't work (on macOS v10.12 or later)?


@txhaflaire talk to your Apple reps. They now have a GSX integration just for pulling warranty information without keeping a technician certified. As far as I've gleaned, its for new GSX customers and requires a minimum number of managed devices.


@Reno sounds awesome, do you mean by Apple Reps, our authorized repair centre for reparations?


@txhaflaire no, Apple has account executives and systems engineers that visit Universities regularly. I heard of this new option through the engineer assigned to my institution. If you don't have a regular contact at Apple, I'd call 1-800-MY-APPLE.


@Rklaffo1, I tested your line to open Safari with the URL and it works just fine for me when I click the button. I used my Jamf Pro server and ran the script entirely through Self Service.



That leads me to believe your code is correct but that something may be amiss with your test computer. Have you tried another computer?



Also, in your testing, does Safari actually launch? If not, try removing the command to use Safari to open the URL and just open the URL directly. Or does Safari open but not display the URL? Test with a different simple URL like 'https://www.apple.com'. Can your computer reach that site?


@milesleacy Sorry, I need to clarify what I was saying. The method of getting the full model name from the plist works fine. And I don't know of a case where it produces the wrong results. What I meant was, the model names that appear there are not worded the same as what you see from the Apple menu's About this Mac window.



Here's an example.
My Mac is a Mid 2015 15" MBP model. in the "About" window, it displays MacBook Pro (Retina, 15-inch, Mid 2015)
If I get the model name from that plist, it shows 15" MacBook Pro with Retina display (Mid 2015)
So as you can see, it's the same machine and similar full model names, just worded a bit differently, or parts are rearranged, etc. It's not a huge deal. Just something to be aware of when using it.
As an aside, there is a way to get that actual name that shows up in the About This Mac window, but it involves doing a query against one of Apple's pages using part of the machine's serial number. It works, but it's not an offline method.



Anyway, glad the adjustment helped.


Thanks @mm2270



That makes sense.



If I were using the “marketing model name” strings as keys in further logic, that would be a concern.



Since I use this dialog simply for human information, the slight difference in syntax shouldn’t be a problem.



Good to be aware of these things though so I don’t later try to execute logic on these strings!


@talkingmoose, tried as you suggested and got the below:



Script result: Last Password Calc 1 =
Last Password Calc 2 =
time Stamp Today = 1536568846
time Since Change = 13181042446
days Since Change = 152558



Thanks


Thanks for making this available, @talkingmoose.



We're testing out the following for Time Machine information:



###
# Time Machine
###

tmDestinationInfo=$( /usr/bin/tmutil destinationinfo )

if [[ "${tmDestinationInfo}" == *"No destinations configured"* ]]; then

tmStatus="No destination configured"

else

runCommand=$( /usr/bin/tmutil destinationinfo | /usr/bin/grep "Name" | /usr/bin/awk '{print $NF}' )
tmStatus="Destination: $runCommand"

fi



if [[ "${tmDestinationInfo}" == *"No destinations configured"* ]]; then

tmLastBackup="Latest Backup: N/A"

else

runCommand=$( /usr/bin/tmutil latestbackup | /usr/bin/awk -F "/" '{print $NF}' )

if [[ -z $runCommand ]]; then

tmLastBackup="Latest Backup: Unknown; connect destination"

else

tmLastBackup="Latest Backup: $runCommand"

fi

fi


… and for the user display:



----------------------------------------------
TIME MACHINE

$tmStatus
$tmLastBackup

Enterprise Connect information …



###
# Enterprise Connect
###

loggedInUser=$( /usr/bin/stat -f %Su "/dev/console" )
testFile="/Applications/Enterprise Connect.app/Contents/SharedSupport/eccl"

if f -f "${testFile}" ]] ; then

ecclPath="/Applications/Enterprise Connect.app/Contents/SharedSupport/eccl"
adUsername=$( /usr/bin/su - "${loggedInUser}" -c "${ecclPath} -p adUsername" | /usr/bin/sed 's/adUsername: //' )
adArePasswordsSynced=$( /usr/bin/su - "${loggedInUser}" -c "${ecclPath} -P | /usr/bin/sed 's/test password sync: //'" )
ecVersion=$( /usr/bin/su - "${loggedInUser}" -c "${ecclPath} -v" | /usr/bin/sed 's/Version: //' )
ecVersion="Version: $ecVersion"

if f ${adUsername} == "missing value" ]]; then # Enterprise Connect installed, but user is NOT logged in

ecUsername="${loggedInUser} NOT logged into Enterprise Connect"

else # Enterprise Connect installed and the user is logged in

ecUsername="Username: ${adUsername}"

fi

else

ecUsername="${loggedInUser} NOT logged into Enterprise Connect; eccl missing"

fi

if f ${adArePasswordsSynced} == "true" ]] ; then

ecPasswordSyncStatus="Password in sync with Active Directory"

# Maximum password age in days
maximumAge=30
lastPasswordSet=$( /usr/bin/su - "${loggedInUser}" -c "${ecclPath} -a pwdLastSet | /usr/bin/sed 's/pwdLastSet: //'" )

# Calculations
lastPasswordCalc1=$(( $lastPasswordSet / 10000000 - 1644473600 ))
lastPasswordCalc2=$(( $lastPasswordCalc1 - 10000000000 ))
timeStampToday=$( date +%s )
timeSinceChange=$(( $timeStampToday - $lastPasswordCalc2 ))
daysSinceChange=$(( $timeSinceChange / 86400 ))
daysRemaining="Password expiration: $(( $maximumAge - $daysSinceChange )) days"


else

ecPasswordSyncStatus="Password is NOT in sync with Active Directory"
daysRemaining="Password expiration: Unknown; login to Enterprise Connect"

fi


… and for the user display:



----------------------------------------------
ENTERPRISE CONNECT

$ecUsername
$ecVersion
$ecPasswordSyncStatus
$daysRemaining

@talkingmoose I have tried now on two different devices. Neither one will even launch the browser to go to the url. I get the message that Remote Support is enabled, but that is it however.


Cisco AnyConnect VPN IP address …



# Cisco AnyConnect VPN IP address
testFile="/opt/cisco/anyconnect/bin/vpn" # Cisco VPN binary

if f -f "${testFile}" ]] ; then
# Cisco AnyConnect installed; read current IP Address
vpnIP=$(/opt/cisco/anyconnect/bin/vpn stats | grep "Client Address (IPv4):" | awk '{print $4}')

if f "${vpnIP}" != "" ]]; then
# IP address is *not* blank, report the IP address
vpnIPaddress="VPN IP Address: ${vpnIP}"
else
# IP address is blank, report no connection
vpnIPaddress="No VPN Connection"
fi

else

# Cisco AnyConnect is not installed
vpnIPaddress="Cisco AnyConnect not found"

fi


… and for the user display:



----------------------------------------------
NETWORK

$activeServices
$SSID
$vpnIPaddress
$SSH
$timeInfo
$timeServer

What would be the command to expand the width of the dialog box?


@sdunbar, sorry for the delayed response. I've been traveling the past week.



According to your test results, the first two password calculations are failing to return anything.



Script result: Last Password Calc 1 =
Last Password Calc 2 =
time Stamp Today = 1536568846
time Since Change = 13181042446
days Since Change = 152558


"Last Password Calc 2" is dependent on the prior "Last Password Calc 1" returning something useful. It too has a variable where we probably need to verify what it's returning.



Can you add the following echo statements and let's see what they're returning as well?



# Get current user
currentUser=$( stat -f "%Su" /dev/console )
echo "Current user = $currentUser"

# Last password set date
lastPasswordSet=$( dscl "/Active Directory/$domainName/All Domains" read "/Users/$currentUser" SMBPasswordLastSet | awk '{print $2}' )
echo "Last Password Set = $lastPasswordSet"

@Rklaffo1, sorry for the delayed response.



Instead of the URL, sounds like opening Safari (or any browser?) is the issue. Let's capture what's happening.



Take your existing command:



/usr/bin/open -a "/Applications/Safari.app" 'https://mercymeetings.webex.com/mw3200/mywebex/default.do?siteurl=mercymeetings'


and fit it into these next two lines:



result=$( /usr/bin/open -a "/Applications/Safari.app" 'https://mercymeetings.webex.com/mw3200/mywebex/default.do?siteurl=mercymeetings' 2>&1 )
echo "Open command returned: $result"


If your command is returning any error message, it will store the information into the "result" variable. The echo statement will make the result appear in your policy log after running it. View the policy log and see if that helps you understand what's happening. We can troubleshoot from there.



One last thing, don't test using the Mojave beta. With its new Privacy Preferences Policy Control feature, this stands a likely chance of failing.


@a.simmons, the script is calling AppleScript to display the dialog window. Unfortunately, Applescript dialogs aren't configurable and you can't widen them further.



Other dialog window options such as python's Tkinter, Cocoa Dialog or Pashua can give you more control over appearance, but those are out of my skillset.


@talkingmoose



Thanks for getting back to me, here is what those 2 lines are returning.



Script result:
Current user = sdunbar
Last Password Set = source
Last Password Calc 1 =
Last Password Calc 2 =
time Stamp Today = 1537169935
time Since Change = 13181643535
days Since Change = 152565


@sdunbar, excellent! That pinpoints the problem to this line:



lastPasswordSet=$( dscl "/Active Directory/$domainName/All Domains" read "/Users/$currentUser" SMBPasswordLastSet | awk '{print $2}' )


Is there a possibility you haven't updated the domainName variable from "TALKINGMOOSE" to your own domain name? This is not an Active Directory domain name such as "talkingmoose.pvt". It's a NetBIOS domain name. This command should return your NetBIOS domain name. Does it return the correct name?



/usr/bin/dscl "/Active Directory/" -read / SubNodes | awk -F ": " '{print $2}'



Or, is there a possibility this Mac isn't bound to AD or you're not logged in with an AD account? Remember, a local macOS account with the same username as an Active Directory account will always take precedence.


Reply