Custom Fields and Multi-Lined Outputs
Description
Custom Fields are useful for returning small, reportable values that are not part of standard inventory. When a script finds a long list of results, return a concise value in the Custom Field and store the full list somewhere easier to read.
Information
A scripted Custom Field uses the script output as the inventory value. If the script discovers many items, decide what short value should appear in inventory and where the full output should be stored for review.
- What is the best information to return as a value, which can concisely provide meaningful information
- Where is the best place to store the required values for reference
For example, macOS 10.15 and later do not run 32-bit apps. A script that returns every 32-bit item as the Custom Field value would be hard to read and search. A better pattern is to return the count as an integer, then store the detailed list in the FileWave Client log.
The required list of 32-bit Apps, though, still needs to be stored, preferably located in an easy to obtain location for analysis.
Details
Continuing with the example, as of macOS 10.15 Apple dropped support for 32-bit Apps. Consideration was then required for listing 32-bit Apps on devices prior to upgrading to 10.15, such that software upgrades or alternate software could be implemented to replace those utilised. For this example the chosen options are:
- Return the quantity of 32-bit Apps as an Integer
- Output the list of 32-bit Apps into the FileWave Client log.
With the count stored as an integer, Inventory Reports (formerly Queries) can target devices with the highest number of 32-bit apps first. As software is replaced, the count should drop until all affected apps have been handled.
The FileWave Client log can be reviewed from FileWave Central. Use a consistent keyword in the script output so the detailed list is easy to find.
The script could look something like the following, which consists of:
- A python section to provide a dated format to match the current log
- A function to define the output if either an Application or Framework has been located (consideration has been made to identify Apps with Apps or within Frameworks, etc)
- A default output for any other identified binary, library, etc
- A command to identify the apps, pushed into a loop to trigger the above
- A total count to report back as the overall integer value
#!/bin/zsh
testline=""
linecount=0
logfile=/private/var/log/fwcld.log
function time_formatted {
python - <<END
import datetime
now = datetime.datetime.now()
year = '{:04d}'.format(now.year)
month = '{:02d}'.format(now.month)
day = '{:02d}'.format(now.day)
hour = format(now.hour)
minute = '{:02d}'.format(now.minute)
second = '{:02d}'.format(now.second)
mlsec = format(now.microsecond)
the_time = '{}-{}-{} {}:{}:{}.{}'.format(year, month, day, hour, minute, second, mlsec[:3])
print(the_time)
END
}
function printline {
if [[ "$@" != "$testline" ]]
then
linecount=$(( linecount + 1 ))
echo -e "\t$linecount: $@" >> "$logfile"
fi
testline="$@"
}
echo $(time_formatted)"|main|INFO|CLIENT|Checking for 32bit apps" >> "$logfile"
while read line
do
case "$line" in
*".framework"*)
printline $(echo "$line" | awk -F "\\\.framework" '{print "32bit app|Application|"$1".framework"}')
;;
*".app"*)
printline $(echo "$line" | awk -F "\\\.app" '{print "32bit app|Framework|"$1".app"}')
;;
*)
linecount=$(( linecount + 1 ))
echo -e "\t$linecount: 32bit app|Other|$line" >> "$logfile"
;;
esac
done< <(mdfind "kMDItemExecutableArchitectures == '*i386*' && kMDItemExecutableArchitectures != '*x86*'")
echo $linecount
echo -e "\tTotal 32bit apps found: $linecount" >> "$logfile"
To view the detailed list, open Client Monitor > Client Log and search for 32bit app. The output may look like this:
Pulling a log via client monitor requires a connection from your admin directly to the client. Client firewall, NAT, and Network ACL might prevent this from happening. Default TCP and UDP Port Usage
2019-07-20 15:46:31.373|main|INFO|CLIENT|Checking for 32bit apps
1: 32bit app|Framework|/Users/rstehpens/Documents/Papercut MF Clent/mac/legacy/PCClient.app
2: 32bit app|Framework|/Users/rstehpens/Documents/Papercut MF Clent/mac/legacy/client-local-install.app
3: 32bit app|Framework|/Applications/BBEdit.app
4: 32bit app|Framework|/Applications/Adobe Connect/Adobe Connect.app
5: 32bit app|Framework|/Applications/RingCentral Meetings.app
6: 32bit app|Application|/System/Library/Frameworks/CoreServices.framework
7: 32bit app|Application|/System/Library/Frameworks/Carbon.framework
8: 32bit app|Other|/usr/bin/vmmap32
9: 32bit app|Other|/usr/bin/stringdups32
10: 32bit app|Other|/usr/bin/malloc_history32
11: 32bit app|Other|/usr/bin/leaks32
12: 32bit app|Other|/usr/bin/heap32
13: 32bit app|Other|/Users/rstehpens/Desktop/UserData/BigHonkingText
14: 32bit app|Application|/System/Library/Frameworks/QuickLook.framework
15: 32bit app|Framework|/System/Library/Input Methods/InkServer.app
16: 32bit app|Application|/System/Library/Frameworks/DrawSprocket.framework
17: 32bit app|Application|/System/Library/Frameworks/Scripting.framework
18: 32bit app|Application|/System/Library/Frameworks/DVComponentGlue.framework
19: 32bit app|Application|/System/Library/Frameworks/QuickTime.framework
20: 32bit app|Application|/System/Library/Frameworks/AppKitScripting.framework
21: 32bit app|Application|/System/Library/Frameworks/DiscRecording.framework
22: 32bit app|Application|/System/Library/PrivateFrameworks/CoreMediaAuthoring.framework
23: 32bit app|Application|/System/Library/PrivateFrameworks/vmutils.framework
24: 32bit app|Application|/System/Library/PrivateFrameworks/CoreMediaPrivate.framework
25: 32bit app|Application|/System/Library/PrivateFrameworks/CoreMediaIOServicesPrivate.framework
26: 32bit app|Application|/System/Library/PrivateFrameworks/GraphicsAppSupport.framework
27: 32bit app|Application|/System/Library/PrivateFrameworks/FWAVCPrivate.framework
28: 32bit app|Other|/System/Library/Printers/Libraries/libConverter.dylib
29: 32bit app|Other|/sbin/autodiskmount
30: 32bit app|Other|/usr/sbin/pictd
31: 32bit app|Other|/usr/lib/libnetsnmp.5.2.1.dylib
32: 32bit app|Other|/usr/bin/qtdefaults
33: 32bit app|Other|/usr/bin/qc2movie
34: 32bit app|Framework|/usr/local/bin/iHook.app
35: 32bit app|Other|/Users/rstehpens/Library/Android/sdk/build-tools/28.0.3/mipsel-linux-android-ld
36: 32bit app|Other|/Users/rstehpens/Library/Android/sdk/build-tools/28.0.3/i686-linux-android-ld
37: 32bit app|Other|/Users/rstehpens/Library/Android/sdk/build-tools/28.0.3/arm-linux-androideabi-ld
38: 32bit app|Other|/Users/rstehpens/Library/Android/sdk/tools/mksdcard
39: 32bit app|Framework|/Library/Application Support/Microsoft/Silverlight/OutOfBrowser/SLLauncher.app
40: 32bit app|Other|/Users/rstehpens/Scripts/bin/BigHonkingText
41: 32bit app|Other|/Users/rstehpens/Downloads/Safari/BigHonkingText106
42: 32bit app|Framework|/Users/rstehpens/Library/Application Support/WebEx Folder/T31_UMC/Meeting Center.app
43: 32bit app|Other|/Users/rstehpens/Library/Application Support/WebEx Folder/T31_UMC/libopenh264-0.6.6.0.dylib
44: 32bit app|Other|/Users/rstehpens/Library/Application Support/WebEx Folder/T31_UMC/libcrypto-1.6.2.9.dylib
45: 32bit app|Other|/Users/rstehpens/Library/Application Support/WebEx Folder/T31_UMC/libssl-1.6.2.9.dylib
46: 32bit app|Framework|/Users/rstehpens/Library/Application Support/WebEx Folder/T31_UMC/atmsupload.app
47: 32bit app|Framework|/Users/rstehpens/Library/Application Support/WebEx Folder/T31_UMC/convertpdf.app
48: 32bit app|Other|/Users/rstehpens/Library/Application Support/WebEx Folder/T31_UMC/xml-31.0.0.1.dylib
49: 32bit app|Other|/Users/rstehpens/Library/Application Support/WebEx Folder/T31_UMC/cmcrypto-31.11.0.1.dylib
50: 32bit app|Framework|/Users/rstehpens/Library/Application Support/WebEx Folder/T31_UMC/asannotation2.app
Total 32bit apps found: 50
This kind of list is too long for a useful Custom Field value. The count gives you something sortable and reportable, while the log keeps the detailed evidence available.
There are other ways the information could be stored or viewed. Scripts ran through Filesets, e.g. Activation, Preflight, etc. store the output and may be viewed via Fileset Status. These scripts have the difference in that they are usually ran just once, which may be better or worse depending upon the use case. Additionally, scripts can include API calls to alter values in Administration Custom Fields.
Use the same pattern for other scripted Custom Fields: return the small value you need for reporting, and store long supporting output somewhere admins can actually read.
No comments to display
No comments to display