Build a Computer Information script for your Help Desk

talkingmoose
Moderator
Moderator

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"

05b901f8301343f282683f0a1a0b8f47

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

80 REPLIES 80

sdunbar
Contributor

@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

dan-snelson
Valued Contributor II

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

dan-snelson
Valued Contributor II

Enterprise Connect information …

###
# Enterprise Connect
###

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

if [[ -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 [[ ${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 [[ ${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

Rklaffo1
New Contributor II

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

dan-snelson
Valued Contributor II

Cisco AnyConnect VPN IP address …

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

if [[ -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 [[ "${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

a_simmons
Contributor II

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

talkingmoose
Moderator
Moderator

@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"

talkingmoose
Moderator
Moderator

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

talkingmoose
Moderator
Moderator

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

sdunbar
Contributor

@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

talkingmoose
Moderator
Moderator

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

chris_kemp
Contributor III

Was messing around with this script this morning, since we have an similar script that needs some updates. I changed the AD check portion, because if the machine is unbound then it returns "Fail" as the test status - I think this is a bit confusing, since it's not a "Fail" so much as it doesn't really matter ;-) so I set up an extra loop to set status to "N/A" if the machine is not bound, as opposed to a legit failed connection:

#!/bin/sh

# Test Active Directory binding
runCommand=$( /usr/bin/dscl "/Active Directory/your_domain_here/All Domains" read /Users )

if [ "$AD" = "Yes" ]; then
    if [ "$runCommand" = "name: dsRecTypeStandard:Users" ]; then
        testAD="Test Active Directory Connection: Success"
    else
        testAD="Test Active Directory Connection: Fail"   
    fi
else
    testAD="Test Active Directory Connection: N/A"
fi

sdunbar
Contributor

@talkingmoose

Great! that has sorted it. I did change the domain name, but it was not correct. now all showing correctly.

Many thanks for all your help, very much appreciated.

Rklaffo1
New Contributor II

Disregard figured it out Was trying to figure out a way that the information that is within the window can be automatically copied over to a text document on the users computer. Still learning a lot in the scripting world and didn't know if anyone could help with this as my searches have come up with null.

bcbackes
Contributor III

@dan-snelson I've tried to add your Enterprise Connect script above, however, I'm not able to get it working. I'm not sure what I'm doing wrong. The weird thing is when I click on Self-Service Icon it doesn't appear to run. There's no output window, no nothing. If I take out the Enterprise Connect part it works fine by pulling in all other information into the output window.

I did try the Password script that @sdunbar had suggested. That works, however, the # of days before my password expires doesn't match what Enterprise Connect tells me when I login to multiple Macs.

Any ideas? I'm using a login account that doesn't have admin rights. I did implement the Anyconnect VPN IP address script. That works perfectly.

Big shout out to everyone on this page. I went through all the feedback everyone has provided and I've setup one that works for my environment. I just have some last minute touches to do.

swapple
Contributor III

I clicked on the links in the article to get the script and got a 404, went to the GitHub and did not see it.

scottb
Honored Contributor

@swhps - might want to put up what link isn't working as there's a ton of info in this thread...

swapple
Contributor III

The one in the blog jamf published "Build a Computer Information script for your Help Desk"

https://github.com/jamfprofessionalservices/Jamf-Scripts/blob/master/Computer%20Information.bash

I saw in slack they are updating it soon.

talkingmoose
Moderator
Moderator

Until the blog post gets fixed, here's a direct link:

https://github.com/talkingmoose/Jamf-Scripts/blob/master/Computer%20Information.bash

SVM-IT
New Contributor III

We're going to be using this script in our environment, but I've run into the following issue:

"If fast user switching is enabled, and two persons are logged onto a computer, and the script is run by the second person that logged onto the computer, the results are displayed on the first user's screen and not the screen of the person that ran the script."

Found the answer to my question here:
https://scriptingosx.com/2018/04/demystifying-root-on-macos-part-3-root-and-scripting/

scottb
Honored Contributor

Hi all, looking to do something "related" to this. We have clients without any sort of LDAP, and I need to pull into the JSS user info such as:
Name
Email
Location
Phone
Using the ARD fields 1-4, we can pull that into inventory. What I'd like to be able to do is have a popup (AppleScript? Bash?) to query them for the four fields as opposed to them opening System Preferences/Sharing and filling in if possible.
This allows for filling, but I'm not sure how to utilize that to do the task of automating the fills.

sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -configure -computerinfo -set1 -1 "value for field 1" -set2 -2 "value for field 2"

DMH2000
Contributor

Newby here... I know this is an old post but had a question about opening an Outlook message and populating the Computer Information in the body of the message. I get a message 'file does not exist' for all text in the log. The only change to Bill's script is putting in 'com.microsoft.outlook' to call Outlook. Does anyone have an idea how this can get imported into the body of the message correctly?

Hopefully to explain better, I tested it in Terminal and confirmed. As seen below, 'displayInfo' has a space in it, thus throws the same error as the script (because the body of the Computer information has spaces). If I put displayInfo="qwerty%2012345", it works fine. The message opens up and populates with qwerty 12345. I also needed a %20 for the Subject as seen below.

Here is my test commands from terminal, which basically is the same as what Bill's script is calling.

displayInfo="qwerty 12345"

/usr/bin/open -b com.microsoft.outlook "mailto:test@somedomain.com?subject=Computer%20Information&body=$displayInfo"

The file /Users/'MyName'/mailto:test@somedomain.com?subject=Computer%20Information&body=qwerty 12345 does not exist.

sdagley
Esteemed Contributor II

@DMH2000 The -b com.microsoft.outlook in your script causes the open command to call Outlook telling it to open the file named by the quoted data, not handle the mailto: URL that data actually represents. To make Outlook be the default mailto: handler, run the MailToOutlook package on your Macs to and remove the -b com.microsoft.outlook from your script

已不18好多年
New Contributor

Just would like to know, if the mailto still working on newest os system, whatever I tried the mail to, it gives error message with file does not exist.
I can use the following script to trigger Apple mail , thanks @Andrina and @rderewianko

#!/bin/sh
/usr/bin/osascript -e "
    tell application "Mail"
    set theContent to ("${displayInfo}")
    set theEmail to make new outgoing message with properties {visible:true, subject:"Computer Information ($serialNumber)", content:theContent}
    tell theEmail
        make new recipient at end of to recipients with properties {address:"shanghai.it.help@nyu.edu"}
    end tell            
    end tell"

but to simplify the script, the mailto seems better.

Also is there a way to trigger web gmail to send the information?

DMH2000
Contributor

@sdagley I have done that and still fails with 'message with file does not exist' as @rc156 states. I think it is an HTML issue, as I had to add %20 to get 'subject=Computer%20 Information' to complete to that point..

sdagley
Esteemed Contributor II

@DMH2000 It sounds like you're still doing something that's launching Outlook directly rather than invoking it as the mailto: handler. The following works as expected for me on macOS Catalina with Outlook set as the default mailto: handler:

/usr/bin/open "mailto:test@somedomain.com?subject=Computer Information&body=Some random text for the body of a message"

If you copy and paste that line into Terminal on your system what happens?

DMH2000
Contributor

@sdagley The file /Users/My.Name/mailto:test@somedomain.com?subject=Computer Information&body=Some random text for the body of a message does not exist. I should mention this is on Big Sur, but don't think that is the issue.

When I put type in /usr/bin/open "mailto:test@somedomain.com?subject=Computer%20Information&body=Some%20random%20message" a new message opens...
475f1891f8934d099a449b52367199dd

sdagley
Esteemed Contributor II

@DMH2000 Why your Mac thinks it needs to open a file with the contents of the mailto: URL is the mystery that needs to be solved. What does a simple /usr/bin/open "mailto:" do? It should open Outlook with a mail compose window.

DMH2000
Contributor

@sdagley. It opens a message window. As I edited the message above: When I put type in /usr/bin/open "mailto:test@somedomain.com?subject=Computer%20Information&body=Some%20random%20message" a new message opens...

fredrik_virding
Contributor

Hi,

I did some testing with the email thing as well.

And lo and behold. My conclusion, which could be incorrect of course, is that once i started to specify things, like this:

#!/bin/sh# 
email computer information to help desk
    currentUser=$( stat -f "%Su" /dev/console )
    computerName=$( /usr/sbin/scutil --get ComputerName )
    /usr/bin/open -b com.microsoft.outlook "mailto:$supportEmail?subject=Computer%20Information%20$computerName"

It seemed to pick up the info.

DMH2000
Contributor

@fredrik.virding So why do you have to put %20 there? Also if you use the full Computer Information in the body it fails because it isn't formatted as HTML.... I really don't know the resolution, I even tried to make Outlook default message as Plain Text, but that didn't help either.

fredrik_virding
Contributor

@DMH2000

To be honest, i have no clue why it acts like it does. Perhaps someone can help me clarify.

My personal thought is that it seems the script acts as two separate things. The first compiles and shows the info accordingly in the pop-up, whilst the email one is not able to read that info.

Im working on some more testing to see what can be done.

scottb
Honored Contributor

Here are the bones of something I tried to do a few years back and got close, but not quite there. It doesn't run in BS, but at the time - macOS 10.13/10.14 it did. Since I suck at code, it was a journey and when I had it almost working, the clients decided they didn't care about who owned what ¯_(ツ)_/¯

#!/bin/bash

jamfHelper="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper"

description="Attention: the JAMF team do not have a complete record of who uses this Mac.

We need to know who you are so as to send you instructions on how to enable Encryption and AV.

Please email me@company.com using the 'Send Email' button below.  Everything will be populated for you."

button1="Send Email"
#button2="Send Email"
logo="/Library/Application Support/company/company.png"
serial_number='Serial Number'=$(ioreg -rd1 -c IOPlatformExpertDevice | awk -F'"' '/IOPlatformSerialNumber/{print $4}')
currentuser='Current User'=$(python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");')
ComputerName='Computer Name'=$(scutil --get ComputerName)
## location=Location=$(curl https://ipapi.co/timezone)

if [[ ${osvers} -lt 7 ]]; then
    userChoice=$("$jamfHelper" -windowType hud -description "$description" -button1 "$button1" -icon "$logo")
    if [ "$userChoice" == "0" ]; then sleep 10
        open -b com.microsoft.outlook "mailto:me@company.com?subject=Mac Info for Company&body=$serial_number

$currentuser
$ComputerName

Just click 'Send' now.  Thank you!"

    else
        exit 0
        fi

fi

saikat_tripathi
New Contributor II

@scottb I tried your script using SelfService but getting this error "Just click 'Send' now. Thank you! does not exist."

emily
Valued Contributor III
Valued Contributor III

Just chiming in since there is still activity on this topic… The Support App by Root3 (NL) was recently added to the Jamf Marketplace and it's seriously awesome. Definitely worth checking out if you're wanting a way to display helpful data to your users, and it's customizable with a configuration profile.

Support App on the Jamf Marketplace (Support App on GitHub)

davidhiggs
Contributor III

hey that looks great, thanks @emily !

fredrik_virding
Contributor

@emily

Very nice info! Have you tried it? Trying to get the custom logo to work, but not sure how to make it work.

emily
Valued Contributor III
Valued Contributor III

@fredrik.virding I haven’t used it myself yet but I can try to tuck aside some time this week and see what I can come up with. The Mac Admins Slack may be another good resource for tip or some feedback on how to use it.

fredrik_virding
Contributor

@emily

Noted! The rest of the features was pretty straight forward. Super slick.

ThomasGL
New Contributor

Hello everyone,
I'm new to scripting and this helpdesk script is really great.
On the other hand, I would like the Mac address to be found in addition to the IP address when this command is used.

networkServices=$( /usr/sbin/networksetup -listallnetworkservices | /usr/bin/grep -v asterisk )
	
	while IFS= read aService
	do
		activePort=$( /usr/sbin/networksetup -getinfo "$aService" | /usr/bin/grep "IP address" | /usr/bin/grep -v "IPv6" )
		if [ "$activePort" != "" ] && [ "$activeServices" != "" ]; then
			activeServices="$activeServices\n$aService $activePort"
		elif [ "$activePort" != "" ] && [ "$activeServices" = "" ]; then
			activeServices="$aService $activePort"
		fi
	done <<< "$networkServices"
	
	activeServices=$( echo "$activeServices" | /usr/bin/sed '/^$/d')

After several hours of searching, I can't find the solution so I'm asking you for help.