UEMB260 – Define and Maintain a Desired State Configuration on your Macs Using Custom Scripts and LANDESK Patch

Slides: https://appleintheenterprise.files.wordpress.com/2016/05/desired-state-management-os-x-interchange-16.pptx

GitHub: https://github.com/northice/LDMS-Scripts



Efficiently Transfer Files to an OS X Device with SDClient

Have you ever needed to copy a file from a share to a more than one Mac in your environment?  My guess is the answer to that is yes, I know it was for the potential customer I spoke with on the phone today.  Whether you’re trying to apply a configuration file for a package, settings for a proxy server, VPN configuration files or any of the myriad of other reasons, what you’re transferring isn’t the important question, it’s how do you do it.

Luckily sdclient, the tool that is the brains behind all things software distribution for the Mac, has a bunch of goodness via command line switches that can be used to download files and place them into specific locations; all the while still taking advantage of the download technologies built into the agent.

To leverage sdclient, we’ll write a shell script that will tell sdclient what file to download and where to place it.  The entire script is very short.  There will be two variables, one for the source file location and the second for the destination location.

The only thing you need to really pay attention to in regards to the source location is to ensure the file is accessible via http.  You can setup a variable or just supply the location.  I like to create a variable so that the code can be better documented and easier to read for others.  Here is my source variable.


We’ll repeat the process for the destination location.


In addition to the destination variable, the script will include a quick check to ensure the destination folder exists on the end node and if not, create it.

if [ ! -d "$destinationLocation" ]; then
echo "Location doesn't exist.  Creating directory"
mkdir $destinationLocation
echo "$destinationLocation created"

The actual download and placement of the file will be done by sdclient with three switches: -noinstall, -package and –destdir.  The switch names are pretty self-explanatory, the –noinstall tells sdclient to not execute the file that will be downloaded.  The –package switch is where you insert the path to the source file available, again available on the http share.  Lastly, the –destdir switch tells sdclient where to place the file on the Mac client.

All done, your command sdclient command should look something like:

/Library/Application\ Support/LANDesk/bin/sdclient -noinstall -package "$fileToCopy" -destdir "$destinationLocation"

Here is the entire example script.

#  FileTransfer.sh
#  Created by Bennett Norton on 5/16/16.
#  This script will copy a file from the source destination and place it on the Mac into the destination folder
#  Change the path variables

#File to copy
#change this to match your hosted path, it needs to be http

#Location to copy file to
#change this to match your destination path
destinationLocation="/Path/To/Your/Destination/Folder "

#Check to see if destination exists and if not, create it
if [ ! -d "$destinationLocation" ]; then
echo "Location doesn't exist.  Creating directory"
mkdir $destinationLocation
echo "$destinationLocation created"

#Download and execute command
#You shouldn't need to make any changes here
#-noinstall ensure the package does not get executed
#-package is the source url path
#-destdir is the destination url path
/Library/Application\ Support/LANDesk/bin/sdclient -noinstall -package "$fileToCopy" -destdir "$destinationLocation"

As discussed in previous posts, save this file as a .sh file and set the execute permission on it by running the command below.

sudo chmod +x /path/to/script.sh

Once you’ve set the execute permissions, copy the script to your package repository and create a LANDESK Software Distribution package to deploy.

Creating LANDESK Management Suite Mac Packages

  1. Open the LANDESK Console
  2. Navigate to the top menu bar, select Tools > Distribution > Distribution Packages.
  3. In the lower left menu tree, highlight My Packages or Public Packages from within the Distribution Packages window
  4. On the Distribution menu bar, press the New Package button and select New Macintosh Package.
  5. Give the package a name
  6. Provide a description as well as any metadata information desired
  7. Set the primary file to the script file you previously transferred to your package share
  8. Fill out the Metadata details if desired, specifically supplying a logo so it shows up properly in the portal
  9. Save the package

Creating a Scheduled Mac Software Distribution Task

  1. Right click on the Mac software distribution package created and select Create Scheduled Task
  2. From the network view, select and drag the desired machine(s), user(s) or query(ies) and drop them onto the task
  3. Now, right click on the task and select properties
  4. Set the desired Task type under Task Settings as to whether you want a push, a policy or a hybrid of the two types in a policy-supported push
  5. Set the radio button in the Portal Settings to either Recommended or Optional if you desire to put the package into Workspaces.  If you’d like to automatically deploy the app, select Run automatically
  6. Change the Reboot Settings or Distribution and Patch settings if desired
  7. Set the schedule task settings with the appropriate start time


Gain Additional Inventory Insights by Manually Executing the OS X Inventory Scanner

Have you ever had a device that won’t update the core server with its latest inventory scan?  While there are a numerous reasons as to why a scan may not process, unless you execute the inventory scanner manually, or peer into the landesk.log, it can be pretty tough to figure out what the cause might be.

In addition to seeing a real-time view into the scanner, when executing the Inventory Scanner manually, you can add command line switches to customize the scanner.

When I am troubleshooting an inventory issue, I always use the -e -s switches.  The –e switch forces a full hardware and software scan.  By default, the inventory scanner sends up a delta scan (the difference between the current scan and the previous scan), unless being directed to re-baseline the machine.  Using the –e switch will ensure I am forcing a full scan.

The –s switch is signals to the core server that it is to accept this scan, regardless of what it was previously expecting.  Again, because the scanner sends up delta scans, if a device gets out of sync with the core, the sync switch forces the core to accept this scan as the new baseline for the device.

So, to run a scan manually, all you need to do is open up Terminal on a Mac and type:

sudo /Library/Application\ Support/LANDesk/bin/ldiscan -s -e

After hitting Return and providing your admin password, you should see the inventory scanner start posting  all of its actions to the Terminal window.  If the scanner is hanging, you’ll see what action it was on.

If the scanner is able to successfully finish, at the bottom of the output you should see a couple of lines to give additional insight as to why the server might be rejecting the scan.  Look for the lines:

Sending scan file to server: fullyqualfied.domain.name
Status from core = HTTP/1.1 503 Service Unavailable

Pay attention to the status from core line.  The Mac scanner is simply making a standard post to IIS on the core server, so all of your standard IIS return codes apply.  See https://community.landesk.com/docs/DOC-1086 for more information on the IIS status codes.

Also, just for added info, below is a list of all of the command line switches for the Mac inventory scanner.

ldscan [-v1|2|3] [-F ][-R][-c alt_ldms_core] [-l alt_ldappl_path][ -o alt_output_dir][ -t ] [-m mode][-w wait_time][ -h ]
   -c      <name>               - specify which core to send inventory to
   -D                       - force a delta scan.
   -e                       - force a full hardware and software scan
   -F                       - force a full inventory scan
   -h                       - this help screen
   -i                       - ignore user and server preference settings
   -l  <path>               - path to alternate ldappl.ini path
   -L                       - limit downloading of ldappl3.ini
   -m <mode>                - set the scan mode
   -N <name>                - use <name> as the device name in the scan
   -o <path>                - write the scan data to <path> instead of sending it to the core
   -p                       - output full product definitions
   -P                       - don't really scan, just display the scan settings.
   -R                       - reset scan database
   -s                       - perform a synchronization scan
   -T <file>                - send <file> to the core
   -t                       - perform a mini scan
   -u                       - unfiltered output (debugging)
   --v1|2|3                 - report formatted version information
   -V <n>                   - set verbosity level (debugging)
   -w <n>                   - wait <n> seconds  before continuing

Is Your Custom Created PLIST Unreadable and in the Incorrect Format?

Recently I’ve been building all sorts of custom scripts; writing the outputs to a PLIST file. Some of the custom scripts are simple with only a line or two of outputs being written, but other PLIST files have been much more complex with hundreds of output lines.

Despite my best efforts in paying attention to all of the small details, such as ensuring I have properly typed in the correct syntax for each key, occasionally I’ll run into an error when I try to open the PLIST file with Xcode.

Data Couldn't Be Read

The Data Couldn’t Be Read Because it isn’t in the Correct Format

I should mention that TextWrangler will open and display the file just fine.  So using Xcode is a good way to validate your PLIST file has been properly built.

Luckily, OS X includes a utility, plutil, that will give you the exact line number and hopefully an insightful error code as to what the issue is.  To use the utility, all you need to do is follow the 2 steps below.

  1. Launch Terminal
  2. Type in plutil /path/to/your/file/filename.plist

PLUTIL CommandI like to just drag my file into the Terminal window and let the path properly populate.  It’s up to you, you can drag in your file or you can type it out manually. After so doing, you should receive some information similar to the text below.

Unknown character '/' (0x2f) in <integer> on line 12

Knowing my error was on line 12, using TextWrangler I opened the file to see what I was writing to line 12 in my output file.  In this specific example, line 12 shows that I forgot to close out the integer key.


BadOutputPlistA quick fix to add in the “<” bracket to my script and now my PLIST is fully functioning and when the LANDESK scanner processes it, I can be more confident the attributes will properly insert.