Posted on 12-28-2016 03:52 PM
Wanted to put this here in case it helps anyone.
To reboot at next start up only, we came up with a PKG that included these three items:
The Launch Daemon loads at startup, and is set to root:wheel and 644 as per Apple, and triggers a script:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.company.RunOnceOnStartupOnly-recon</string>
<key>ProgramArguments</key>
<array>
<string>/Library/Company/Scripts/RunOnceOnReboot-recon.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
Script uses /usr/bin/tee
for logging to send stdout
/stderr
to the same log, and is set to root:wheel and 755 as per Apple. Triggered on startup, it runs recon, then deletes the Launch Daemon, then deletes itself:
#!/bin/sh
# determine path of JAMF binary
os_version="$( system_profiler SPSoftwareDataType -xml | grep -A 2 'os_version</key>' | grep -o 'OS X [0-9]+.[0-9]+' | grep -o '[0-9]+.[0-9]+' )"
major_version="$( /bin/echo "$os_version" | grep -o '[0-9]+.' | grep -o '[0-9]+' )"
minor_version="$( /bin/echo "$os_version" | grep -o '.[0-9]+' | grep -o '[0-9]+' )"
if [ "$major_version" -lt 10 ] || [ "$major_version" -eq 10 -a "$minor_version" -lt 7 ];then
jamfCLIPath="/usr/sbin/jamf"
else
jamfCLIPath="/usr/local/jamf/bin/jamf"
fi
logFile="/Library/Logs/com.company.RunOnceOnStartupOnly-recon.log"
dateStamp="[ $( date +%Y-%m-%d_%R_%Z ) ]"
launchDaemon="/Library/LaunchDaemons/com.company.RunOnceOnStartupOnly-recon.plist"
# Run recon
/bin/echo "$dateStamp Taking a 60 second nap..." 2>&1 | tee -a "$logFile"
/bin/sleep 60
/bin/echo "$dateStamp Starting recon..." 2>&1 | tee -a "$logFile"
"$jamfCLIPath" recon 2>&1 | tee -a "$logFile"
/bin/echo "$dateStamp Finished recon..." 2>&1 | tee -a "$logFile"
# Delete Launch Daemon
if [ -e "$launchDaemon" ]; then
/bin/echo "$dateStamp Removing Launch Daemon..." 2>&1 | tee -a "$logFile"
/bin/rm "$launchDaemon" 2>&1 | tee -a "$logFile"
else
/bin/echo "$dateStamp Launch Daemon does not exist." 2>&1 | tee -a "$logFile"
fi
# Completed, exiting
/bin/echo "$dateStamp Completed, goodbye." 2>&1 | tee -a "$logFile"
/bin/rm "$0"
Log file goes into the standard location, and includes sufficient logging with date stamp for staff to monitor and troubleshoot /Library/Logs/com.company.RunOnceOnStartupOnly-recon.log
.
The naming convention follows our standard, so anyone who needs to run recon once on startup only can add it to a policy.
Thanks to @Andrina for her help during Jamf Nation 2016 (whether she realized it or not!), to @SeanA for the second set of eyes and insight into some of these methods, and to @henryxyz for the tip on tee
.
Lastly, to head off any notion of unloading the Launch Daemon in this solution, learned the hard way...
HTH,
Don
Posted on 01-03-2017 05:02 AM
For my curiosity, what happens when a launch daemon triggers a script that unloads/deletes said launch daemon? Does unloading kill all child processes including the script itself?
Posted on 01-03-2017 06:37 AM
@cerberusss yes, hence the tweet. ;)
Posted on 01-03-2017 10:37 AM
There is the nifty launchDaemon key:
<key>AbandonProcessGroup</key>
<true/>
I use that whenever I have a launchD run a script that might have to send an e-mail. It keeps child processes from being killed when the launchD exists.
Posted on 01-04-2017 09:02 AM
@donmontalvo Thank you for this script. Works great after few modifications to fit our environment.
Posted on 01-04-2017 05:41 PM
@benbass wow, thanks, I'll test that on the next go!
@EdLuo nice, both valid, appreciated...updated script!
@dan.snelson just noticed your post from a month ago, awesome stuff, hope you don't mind my linking to it...the more ideas the better!
Posted on 01-04-2017 05:48 PM
@donmontalvo Eeyore says: "Thanks for noticing me."