Local script to report version info

Snickasaurus
Contributor

Hello all, hope this can help some of you out if not give you a starting point for your own version reporting script.
Often I am walking from the cafeteria and get stopped or I'm making my way through a cubicle farm to one customer and get pulled aside by another. Either way it almost always ends up being a conversation about software version this or update that. Being that my brain isn't a functioning Casper database (yet) I either have to open the app(s) in question to view it's version number or if it's a plugin that is yelling at them to update I simply rely on good'ol Firefox "about:plugins" url. I decided to write this little gem, package it up and deploy it as /usr/sbin/versions, so a quick:
COMMAND + spacebar
to search for and open Terminal and running "versions" will give me a quick overview of what I need to know.

Does anyone disagree with putting it in /usr/sbin path?

Code below

Edit: Rewrote almost the entire script. Hopefully someone will find it useful. I (or a user) can run this from Self Service when it's not convenient to access the JSS webmin.

#!/bin/sh

# Name    : reportSystemInfo.sh
# Author  : Snickasaurus
# Date    : 20160117
# Purpose : Output a generated system report then open with default browser.
# Sauce     : https://github.com/Snickasaurus/SystemReportToHTML/blob/master/runSystemReport.sh

# Variables
theTitle="System Report for host:  [ $HOSTNAME ]"
theNow=$(date "+%Y/%m/%d at %r %Z")
theStamp="<h2>Created on $theNow by $USER</h2>"

# Begin script
# Remove previously ran report if found.
if [ -e /private/tmp/systemReport.html ]
  then
  rm /private/tmp/systemReport.html
fi

# Functions
function system_info
{
    echo "<h3>System release info</h3>"
    echo "<pre>"
    sw_vers
    echo "</pre>"
}

function show_uptime
{
    echo "<h3>System uptime</h3>"
    echo "<pre>"
    uptime
    echo "</pre>"
}

function drive_space
{
    echo "<h3>Filesystem space</h3>"
    echo "<pre>"
    df -h
    echo "</pre>"
}

function jss_check
{
    echo "<h3>Jss Availability</h3>"
    echo "<pre>"
    jamf checkJSSConnection
    echo "</pre>"
}

function user_list
{
    echo "<h3>User List</h3>"
    echo "<pre>"
    userList=$(dscl /Local/Default -list /Users UniqueID | awk '$2 >= 500 { print $1; }')
    for i in $userList
    do
    echo "$(id -un $i) > $(id -F $i)"
  done
    echo "</pre>"
}

function net_names
{
    echo "<h3>Host Names</h3>"
    echo "<pre>"
    echo "ComputerName  : $(scutil --get ComputerName)"
    echo "HostName      : $(scutil --get HostName)"
    echo "LocalHostName : $(scutil --get LocalHostName)"
    echo "NetBIOSName   : $(defaults read /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName)"
    echo "</pre>"
}

function sw_update
{
    theAUTODOWNLOAD=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload)
    if [ "$theAUTODOWNLOAD" == "1" ]
      then
      theAUTOD="True"
    else
      theAUTOD="False"
    fi

    theACECheck=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled)
    if [ "$theACECheck" == "1" ]
      then
      theACE="True"
    else
      theACE="False"
    fi

    theCUICheck=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist CriticalUpdateInstall)
    if [ "$theCUICheck" == "1" ]
      then
      theCUI="True"
    else
      theCUI="False"
    fi

    theSECDATACheck=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist ConfigDataInstall)
    if [ "$theSECDATACheck" == "1" ]
      then
      theSECD="True"
    else
      theSECD="False"
    fi

    theLASTSUCCESS=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist LastSuccessfulDate | awk '{print $1,$2}')

    echo "<h3>Software Update Settings</h3>"
    echo "<pre>"
    echo "Automatic download updates?        = $theAUTOD"
    echo "Automatic update check enabled?    = $theACE"
    echo "Automatic Critical Update install? = $theCUI"
    echo "Automatic Security & Data install? = $theSECD"
    echo "Last Successful Update             = $theLASTSUCCESS"
    echo "</pre>"
}

function app_data
{
    if [ -f /Applications/Adobe Acrobat XI Pro/Adobe Acrobat Pro.app/Contents/Info.plist ]
      then
      theAAP=$(defaults read /Applications/Adobe Acrobat XI Pro/Adobe Acrobat Pro.app/Contents/Info.plist CFBundleShortVersionString)
    else
      theAAP="Missing"
    fi

    if [ -e /Applications/Safari.app ]
      then
      theFirefox=$(defaults read /Applications/Safari.app/Contents/Info.plist CFBundleShortVersionString)
    else
      theSafari="Missing"
    fi

    if [ -e /Applications/Google Chrome.app ]
      then
      theChrome=$(defaults read /Applications/Google Chrome.app/Contents/Info.plist CFBundleShortVersionString)
    else
      theChrome="Missing"
    fi

    if [ -e /Applications/Firefox.app ]
      then
      theFirefox=$(defaults read /Applications/Firefox.app/Contents/Info.plist CFBundleShortVersionString)
    else
      theFirefox="Missing"
    fi

    if [ -f /Library/Internet Plug-Ins/Flash Player.plugin/Contents/Info.plist ]
      then
      theFlash=$(defaults read /Library/Internet Plug-Ins/Flash Player.plugin/Contents/Info CFBundleShortVersionString)
    else
      theFlash="Missing"
    fi

    if [ -f /Library/Application Support/Oracle/Java/Info.plist ]
      then
      theOracle=$(defaults read /Library/Application Support/Oracle/Java/Info.plist CFBundleShortVersionString)
    else
      theOracle="Missing"
    fi

    if [ -f /Applications/Microsoft Office 2011/Office/MicrosoftComponentPlugin.framework/Versions/14/Resources/Info.plist ]
      then
      theOffice11=$(defaults read /Applications/Microsoft Office 2011/Office/MicrosoftComponentPlugin.framework/Versions/14/Resources/Info CFBundleShortVersionString)
    else
      theOffice11="Missing"
    fi

    if [ -f /Applications/Sophos Anti-Virus.app/Contents/Info.plist ]
      then
      theSophos=$(/usr/libexec/PlistBuddy -c "print :ProductVersion:" /Library/Sophos Anti-Virus/product-info.plist)
    else
      theSophos="Missing"
    fi

    if [ -f /Applications/VMware Fusion.app/Contents/Info.plist ]
      then
      theVMWare=$(defaults read /Applications/VMware Fusion.app/Contents/Info.plist CFBundleShortVersionString)
    else
      theVMWare="Missing"
    fi

    if [ -f /Library/Internet Plug-Ins/Silverlight.plugin/Contents/Info.plist ]
      then
      theSilver=$(defaults read /Library/Internet Plug-Ins/Silverlight.plugin/Contents/Info.plist CFBundleShortVersionString)
    else
      theSilver="Missing"
    fi

    echo "<h3>Application Data</h3>"
    echo "<pre>"
    echo "Chrome            = $theChrome"
    echo "Firefox           = $theFirefox"
    echo "Safari            = $theSafari"
    echo "- - - - - - - - - - - - - - - - - - -"
    echo "Flash             = $theFlash"
    echo "JavaO             = $theOracle"
    echo "Silverlight       = $theSilver"
    echo "- - - - - - - - - - - - - - - - - - -"
    echo "Acrobat Pro       = $theAAP"
    echo "Office 2011       = $theOffice11"
    echo "Sophos AV         = $theSophos"
    echo "VMware Fusion     = $theVMWare"
    echo "</pre>"
}

# Begin script
cat > /private/tmp/systemReport.html <<- EOF
  <html>
  <head>
  <style>
  body {background-color: black; color: white;}
  h1   {text-align: center; color: red;}
  h2   {text-align: center; color: green;}
  h3   {color: blue;}
  p    {text-align: center;}
  </style>
      <title>$theTitle</title>
  </head>
  <body>
      <h1>$theTitle</h1>
      <p>$theStamp</p>
      $(system_info)
      $(show_uptime)
      $(app_data)
      $(drive_space)
      $(jss_check)
      $(user_list)
      $(net_names)
      $(sw_update)

  </body>
  </html>
EOF

open /private/tmp/systemReport.html

exit 0
7 REPLIES 7

dpertschi
Valued Contributor

Do a google search on bin and sbin and you'll get reams of opinion.
I think the general consensus is to use /usr/local/bin

I see value in this idea as well. I'm working on a similar project to do the same thing but make it executable from Self Service, bringing up a dialog with the results.

davidacland
Honored Contributor II
Honored Contributor II

Thanks, thats pretty handy!

Do you have a copy in github, I've got a few ideas for it already!

Snickasaurus
Contributor

@dpertschi Thanks for your comment. I'll definitely do some more reading on /usr/local/bin

@davidacland You're welcome and thanks for the comment. I'll add it to my Git today and post back here with the link.

tlarkin
Honored Contributor

This information is all accessible via the API as well. However, if the device has not submitted inventory it may not be up to date when you do the API call.

example code:

curl -k -u tlarkin https://casper9gm.local:8443/JSSResource/computers/id/10 | xpath //application

Example output:

<application><name>Activity Monitor.app</name><path>/Applications/Utilities/Activity Monitor.app</path><version>10.10.0</version></application>-- NODE --
<application><name>Adobe Flash Player Install Manager.app</name><path>/Applications/Utilities/Adobe Flash Player Install Manager.app</path><version>16.0.0.305</version></application>-- NODE --
<application><name>AirPort Utility.app</name><path>/Applications/Utilities/AirPort Utility.app</path><version>6.3.4</version></application>-- NODE --
<application><name>App Store.app</name><path>/Applications/App Store.app</path><version>2.0</version></application>-- NODE --

I will say I really like the idea of having something like an, "Application Version Check," in Self Service. Where users can click a button and show all their current software versions. You could also use an API script with read only access to pull down all their information and then take that XML and have Safari display it or something.

Also, it is not quite as pretty when it comes to output but mdfind can output all application versions very quickly with some simple one liners like this:

mdfind -onlyin /Applications 'kMDItemContentType==com.apple.application-bundle' -attr "kMDItemVersion"

After hacking together a quick script for POC purposes you could create a policy that runs this command, dumps it into a text file and then opens it, then deletes said text file for next time to be ran.

#!/bin/bash

# get list of all current apps installed and display in a dialog box to end user

appVersionList=$(mdfind -onlyin /Applications 'kMDItemContentType==com.apple.application-bundle' -attr "kMDItemDisplayName" -attr "kMDItemVersion" | sed 's/^.*kMDItemDisplayName//' |  sed 's/kMDItemVersion//g' | tr '=' '	' | sort >> /tmp/applist.txt)

open -a TextEdit /tmp/applist.txt

sleep 15 # make sure the file exists long enough for text edit to read it

rm /tmp/applist.txt

exit 0

Not the prettiest one liner, but it seems to work. Perhaps someone here could improve it and maybe toss it in a dialog box or something a bit more fancy.

Cheers,
Tom

Snickasaurus
Contributor

To: @dpertschi , @davidacland and @tlarkin as an update to this project I was working on and to @emilykausalik because of your lurking presence and SelfService mastery.

Here is a script I started from scratch and does the following:
1) Runs a bunch of stuff to collect info
2) Exports to an HTML file
3) Opens in whatever is set as the default browser

To: Tom

I never came back and commented on your work with the api stuff and I do want to send a big thank you for the quick tutorial on api commands and the mdfind oneliner. Neither of which I've messed with but have made notes on so in the future I can add them to my toolbox (especially the API stuff. I find it VERY interesting what people are doing with it theses days).

End: Tom

So here is my latest and greatest attempt to do something geeky and perhaps provide new scriptwriters a few examples of cool stuff you can do.

This could be a packaged script that is deployed in your imaging config to a location in your PATH (so you or a tech and pull up Terminal on a client machine an run the script easily) or added to Self Service and scoped to whomever you desire to have access to it.

Hope this helps someone. I'm posting this after showing @keaton today while we were on the phone discussing a super weird Filevault 2 issue I'm suffering from.

WHAT TO EDIT - With your fav text editor search for "MyCompany" and you will see where the report is saved. (4 places)

#!/bin/bash

# Name    : reportSystemInfo.sh
# Author  : Nick Smith
# Date    : 20160117
# Purpose : Output a generated system report then open with default browser.

# Variables
theTitle="System Report for host:  [ $HOSTNAME ]"
theNow=$(date "+%Y/%m/%d at %r %Z")
theStamp="Created on $theNow by $USER"

#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#
#                                               #
# REMOVE old report if found                    #
#                                               #
#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#
if [ -e /Library/Application Support/MyCompany/report.html ]
  then
  rm /Library/Application Support/MyCompany/report.html
fi
#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#
#                                               #
# REMOVE old report if found                    #
#                                               #
#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#

# Functions
function system_info
{
    echo "<h3>System release info</h3>"
    echo "<pre>"
    sw_vers
    echo "</pre>"
}

function show_uptime
{
    echo "<h3>System uptime</h3>"
    echo "<pre>"
    uptime
    echo "</pre>"
}

function drive_space
{
    echo "<h3>Filesystem space</h3>"
    echo "<pre>"
    df -h
    echo "</pre>"
}

function jss_check
{
    echo "<h3>Jss Availability</h3>"
    echo "<pre>"
    jamf checkJSSConnection
    echo "</pre>"
}

function user_list
{
    echo "<h3>User List</h3>"
    echo "<pre>"
    userList=$(dscl /Local/Default -list /Users UniqueID | awk '$2 >= 500 { print $1; }')
    for i in $userList
    do
    echo "$(id -un $i) <> $(id -F $i)"
  done
    echo "</pre>"
}

function net_names
{
    echo "<h3>Network Names</h3>"
    echo "<pre>"
    echo "ComputerName  : $(scutil --get ComputerName)"
    echo "HostName      : $(scutil --get HostName)"
    echo "LocalHostName : $(scutil --get LocalHostName)"
    echo "NetBIOSName   : $(defaults read /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName)"
    echo "</pre>"
}

function sw_update
{
    theAUTODOWNLOAD=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload)
    if [ "$theAUTODOWNLOAD" == "1" ]
      then
      theAUTOD="True"
    else
      theAUTOD="False"
    fi

    theACECheck=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled)
    if [ "$theACECheck" == "1" ]
      then
      theACE="True"
    else
      theACE="False"
    fi

    theCUICheck=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist CriticalUpdateInstall)
    if [ "$theCUICheck" == "1" ]
      then
      theCUI="True"
    else
      theCUI="False"
    fi

    theSECDATACheck=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist ConfigDataInstall)
    if [ "$theSECDATACheck" == "1" ]
      then
      theSECD="True"
    else
      theSECD="False"
    fi

    echo "<h3>Software Update Settings</h3>"
    echo "<pre>"
    echo "Automatic download updates?        = $theAUTOD"
    echo "Automatic update check enabled?    = $theACE"
    echo "Automatic Critical Update install? = $theCUI"
    echo "Automatic Security & Data install? = $theSECD"
    echo "</pre>"
}

function app_data
{
    if [ -f /Applications/Adobe Acrobat XI Pro/Adobe Acrobat Pro.app/Contents/Info.plist ]
      then
      theAAP=$(defaults read /Applications/Adobe Acrobat XI Pro/Adobe Acrobat Pro.app/Contents/Info.plist CFBundleShortVersionString)
    else
      theAAP="Missing"
    fi

    if [ -e /Applications/Google Chrome.app ]
      then
      theChrome=$(defaults read /Applications/Google Chrome.app/Contents/Info.plist CFBundleShortVersionString)
    else
      theChrome="Missing"
    fi

    if [ -e /Applications/Firefox.app ]
      then
      theFirefox=$(defaults read /Applications/Firefox.app/Contents/Info.plist CFBundleShortVersionString)
    else
      theFirefox="Missing"
    fi

    if [ -f /Library/Internet Plug-Ins/Flash Player.plugin/Contents/Info.plist ]
      then
      theFlash=$(defaults read /Library/Internet Plug-Ins/Flash Player.plugin/Contents/Info CFBundleShortVersionString)
    else
      theFlash="Missing"
    fi

    if [ -f /Library/Application Support/Oracle/Java/Info.plist ]
      then
      theOracle=$(defaults read /Library/Application Support/Oracle/Java/Info.plist CFBundleShortVersionString)
    else
      theOracle="Missing"
    fi

    if [ -f /Applications/Microsoft Office 2011/Office/MicrosoftComponentPlugin.framework/Versions/14/Resources/Info.plist ]
      then
      theOffice11=$(defaults read /Applications/Microsoft Office 2011/Office/MicrosoftComponentPlugin.framework/Versions/14/Resources/Info CFBundleShortVersionString)
    else
      theOffice11="Missing"
    fi

    if [ -f /Applications/Sophos Anti-Virus.app/Contents/Info.plist ]
      then
      theSophos=$(/usr/libexec/PlistBuddy -c "print :ProductVersion:" /Library/Sophos Anti-Virus/product-info.plist)
    else
      theSophos="Missing"
    fi

    if [ -f /Applications/VMware Fusion.app/Contents/Info.plist ]
      then
      theVMWare=$(defaults read /Applications/VMware Fusion.app/Contents/Info.plist CFBundleShortVersionString)
    else
      theVMWare="Missing"
    fi

    echo "<h3>Application Data</h3>"
    echo "<pre>"
    echo "Acrobat Pro       = $theAAP"
    echo "Chrome            = $theChrome"
    echo "Firefox           = $theFirefox"
    echo "Flash             = $theFlash"
    echo "JavaO             = $theOracle"
    echo "Office 2011       = $theOffice11"
    echo "Sophos AV         = $theSophos"
    echo "VMware Fusion     = $theVMWare"
    echo "</pre>"
}

# Begin script
cat > /Library/Application Support/MyCompany/report.html <<- EOF
  <html>
  <head>
      <title>$theTitle</title>
  </head>
  <body>
      <h2>$theTitle</h2>
      <p>$theStamp</p>
      $(system_info)
      $(show_uptime)
      $(drive_space)
      $(jss_check)
      $(user_list)
      $(net_names)
      $(sw_update)
      $(app_data)
  </body>
  </html>
EOF

open /Library/Application Support/MyCompany/report.html

exit 0

davidacland
Honored Contributor II
Honored Contributor II

Thanks @Snickasaurus, been busy!

Just tried it on my Mac, worked perfectly!

Snickasaurus
Contributor

@davidacland Thanks, I know all too well what it's like to be super busy. Updated the script in original post. Give it a try and and let me know what you think.