post script?
The whole script is pretty long but I know the script works fine its just when its run from the LaunchDaemon it behaves odd.
I've also pulled the clean up part of the script out and put it as a one liner at the end of the policy as an "Execute Command". The one liner is "launchctl bootout system /Library/LaunchDaemons/com.MY.LAUNCHD.plist && rm -f /Library/LaunchDaemons/com.MY.LAUNCHD.plist". This works fine and boots the launchDaemon out and deletes it but again seems to kill the JAMF process and there is no recon or any activity after the launchdaemon is booted out and deleted.
It's very odd!
I've also pulled the clean up part of the script out and put it as a one liner at the end of the policy as an "Execute Command". The one liner is "launchctl bootout system /Library/LaunchDaemons/com.MY.LAUNCHD.plist && rm -f /Library/LaunchDaemons/com.MY.LAUNCHD.plist". This works fine and boots the launchDaemon out and deletes it but again seems to kill the JAMF process and there is no recon or any activity after the launchdaemon is booted out and deleted.
It's very odd!
what about if you - lauchctl unload, then delete?
edit.. and what if you move to a background process? you can't && but do you need to?
what about if you - lauchctl unload, then delete?
edit.. and what if you move to a background process? you can't && but do you need to?
unload has the same behaviour :(
Sorry how do you mean move to a background process?
I don't think this is unexpected. If the LaunchDaemon is running the script, then when you direct it to unload or bootout the LaunchDaemon, the script it was running will stop. I think, though not sure, that this is by design, probably to prevent runaway orphaned processes.
I think you will need to rethink how to do this. For example, you can delete the LaunchDaemon plist, so on next bootup, it won't run since the job will not be there in the LaunchDaemons folder. This isn't ideal, since it technically leaves the process running but without it being attached to the job. But it may be an option.
Also, why not do the recon before you try unloading the job or removing it? Is there some reason the inventory collection would need to happen at the very end? You can have the recon happen within the script rather than as an item in the policy.
When you call this from Jamf directly, it of course has no trouble running, and completing, since it wasn't actually called by the LaunchDaemon itself. The jamf process is running independently from the daemon, so it's not affected if the daemon gets stopped.
@perryd84 why does the script need to run with a launch daemon? Couldn't you just run it with a policy with a recurring check-in trigger?
I've also pulled the clean up part of the script out and put it as a one liner at the end of the policy as an "Execute Command". The one liner is "launchctl bootout system /Library/LaunchDaemons/com.MY.LAUNCHD.plist && rm -f /Library/LaunchDaemons/com.MY.LAUNCHD.plist". This works fine and boots the launchDaemon out and deletes it but again seems to kill the JAMF process and there is no recon or any activity after the launchdaemon is booted out and deleted.
It's very odd!
@perryd84 Your script will be terminated when you use bootout to kill the LaunchDaemon. You can definitely rm the files for the script and LaunchDaemon .plist before doing the bootcut though as an rm doesn't remove the file until it's not busy.
Here's the pattern I use to do the final cleanup when I'm triggering scripts via a LaunchDaemon:
# Nuke script and the LaunchDaemon
# Do the rm's before the bootout because the script terminates when the LaunchDaemon is killed
/bin/rm "/Library/Application Support/OrgName/ScriptName.sh"
/bin/rm "/Library/LaunchDaemons/com.orgname.launchdname.plist"
/bin/launchctl bootout system "/Library/LaunchDaemons/com.orgname.launchdname.plist"
I don't think this is unexpected. If the LaunchDaemon is running the script, then when you direct it to unload or bootout the LaunchDaemon, the script it was running will stop. I think, though not sure, that this is by design, probably to prevent runaway orphaned processes.
I think you will need to rethink how to do this. For example, you can delete the LaunchDaemon plist, so on next bootup, it won't run since the job will not be there in the LaunchDaemons folder. This isn't ideal, since it technically leaves the process running but without it being attached to the job. But it may be an option.
Also, why not do the recon before you try unloading the job or removing it? Is there some reason the inventory collection would need to happen at the very end? You can have the recon happen within the script rather than as an item in the policy.
When you call this from Jamf directly, it of course has no trouble running, and completing, since it wasn't actually called by the LaunchDaemon itself. The jamf process is running independently from the daemon, so it's not affected if the daemon gets stopped.
So the launch Daemon is running a JAMF Policy and the policy runs the script. It's almost like the launch Daemon is holding the JAMF process and then kills it when the launch Daemon is booted out. I always thought whatever the daemon is calling runs independent as it's own process?
The recon is just the maintenance payload running an inventory update at the end of the policy but the policy never finishes so the inventory is never updated and JAMF never shows if the policy ran.
@perryd84 why does the script need to run with a launch daemon? Couldn't you just run it with a policy with a recurring check-in trigger?
The daemon is written from another script which puts in a time stamp for the policy to be run. This way I can have it run 5min, 15min, 30min etc and not have to wait for a check-in to run it.
@perryd84 Your script will be terminated when you use bootout to kill the LaunchDaemon. You can definitely rm the files for the script and LaunchDaemon .plist before doing the bootcut though as an rm doesn't remove the file until it's not busy.
Here's the pattern I use to do the final cleanup when I'm triggering scripts via a LaunchDaemon:
# Nuke script and the LaunchDaemon
# Do the rm's before the bootout because the script terminates when the LaunchDaemon is killed
/bin/rm "/Library/Application Support/OrgName/ScriptName.sh"
/bin/rm "/Library/LaunchDaemons/com.orgname.launchdname.plist"
/bin/launchctl bootout system "/Library/LaunchDaemons/com.orgname.launchdname.plist"
This could work.
But the issue I would run into with this is that the bootout part seems to stop the JAMF process running and so then I don't get an inventory update at the end of the policy to say if its run or not.
This could work.
But the issue I would run into with this is that the bootout part seems to stop the JAMF process running and so then I don't get an inventory update at the end of the policy to say if its run or not.
@perryd84 Are you triggering another Jamf Pro policy from your script? If so you will need to make sure that policy has completed before continuing execution of your script.
@perryd84 Are you triggering another Jamf Pro policy from your script? If so you will need to make sure that policy has completed before continuing execution of your script.
No the launch Daemon triggers a policy which runs a script.
So my work around is to as follows:
- Daemon triggers the JAMF policy
- Policy runs the script
- Script does whats it's meant to do then deletes the old/existing daemon
- The script then writes an empty daemon with no trigger or action
- JAMF Policy finishes correctly and shows logs as desired
This way the daemon stays loaded/bootstraped but it will never trigger or do anything until it's written to again at a future time.
Not the cleanest way to do it but running bootout is not an option as it kills the JAMF process. Thanks for all the suggestions I might figure out a nicer way to do this another time.
@mm2270 wrote:
When you call this from Jamf directly, it of course has no trouble running, and completing, since it wasn't actually called by the LaunchDaemon itself.
@perryd84
Does the LaunchDaemon binary have tcc permissions for handoff to the jamf executable, which ultimately then calls the policy?
When you used the 'jamf policy -event' command, everything is initiated by the jamf binary which is likely whitelisted with full disk access (i'm guessing).
The best way to rule this out would be run one or more of the following and see if something pops up in the logs;
/usr/bin/log show --predicate 'subsystem == "com.apple.TCC"' --info --last 1h | grep deny
/usr/bin/log show --predicate 'subsystem == "com.apple.TCC"' --info --last 1h | grep binary_path
/usr/bin/log show --predicate 'subsystem == "com.apple.TCC"' --info --last 1h | grep AttributionChain
Worth a shot to cover this base if you haven't already.
So my work around is to as follows:
- Daemon triggers the JAMF policy
- Policy runs the script
- Script does whats it's meant to do then deletes the old/existing daemon
- The script then writes an empty daemon with no trigger or action
- JAMF Policy finishes correctly and shows logs as desired
This way the daemon stays loaded/bootstraped but it will never trigger or do anything until it's written to again at a future time.
Not the cleanest way to do it but running bootout is not an option as it kills the JAMF process. Thanks for all the suggestions I might figure out a nicer way to do this another time.
Could you elaborate a little more on what the end goal is here? Because if it's what I think it might be, I may have another suggestion for you.
It sounds like you're using this LaunchDaemon as a way to have the Mac immediately run a policy from the Jamf Pro server, similar to how we were once able to do thru Jamf Remote. Is that the end goal? Or is it for some other purpose?
Could you elaborate a little more on what the end goal is here? Because if it's what I think it might be, I may have another suggestion for you.
It sounds like you're using this LaunchDaemon as a way to have the Mac immediately run a policy from the Jamf Pro server, similar to how we were once able to do thru Jamf Remote. Is that the end goal? Or is it for some other purpose?
Yeah something along those lines. I basically want the launch Daemon to run a policy at a set time which is set by a previous policy. So the previous policy sets the Daemon to run after 5min or 10min or 15min etc
Yeah something along those lines. I basically want the launch Daemon to run a policy at a set time which is set by a previous policy. So the previous policy sets the Daemon to run after 5min or 10min or 15min etc
You may want to do something like, craft your LaunchDaemon to watch a file, using the WatchPaths key. On change, the daemon can run the script in it's program argument to check the contents of the file. I recommend a plist. It can have a value in it for the time you specify, for example, 5, 10 or 15 and also any other information, such as a custom event trigger, and when it gathers these details, tell it to do a jamf policy to run the specified policy.
I'm doing something like this by using a special Configuration Profile that I can push over MDM to my Macs. I have a LaunchDaemon that watches the contents of that plist in /Library/Managed\\ Preferences and reads information from the plist. I can have the target devices call almost any policy (in scope of course) on demand by it's policy ID or custom trigger. I don't need to wait for the device to check in on the next scheduled Jamf check-in.
Is that kind of what you're looking to do?