Scripting help needed - launchdaemon

jameson
Contributor II

I would like to create a launchdaemon that launch a script when finder and dock processes are existing.  I don´t know if anyone has something similar running they can try and show . 

the launchdaemon I can create on my own - but how to build in script that it only should run if those dock and finder process exist I struggle to find

46 REPLIES 46

mm2270
Legendary Contributor III

Yeah, this is possible to do. But before I go into how I'm doing this in one of my scripts, I was wondering if what you're trying to run in the LaunchDaemon has to be run as root. If it doesn't need root, then the perhaps easier way to handle this would be to use a LaunchAgent, which by nature, will only run when someone is logged in, meaning there's no need to check for the Dock and/or Finder running.

If what you have to do does need a LaunchDaemon, then here's some code that could work to drop into your script. The basic idea is, you keep looping in the script until the conditions that Dock and Finder are both found as active processes. Once you break out of the loop, the rest of your script can continue.

#!/bin/zsh

dock_process=$(/usr/bin/pgrep -l "Dock")
finder_process=$(/usr/bin/pgrep -l "Finder")
until [[ "$dock_process" && "$finder_process" ]]; do
	/bin/sleep 1
done

echo "Dock and Finder are both running"

 

jameson
Contributor II

Ok thansen 

ok great. Will give it a try if i Can get This built Into a launchdeamon - and yes it must run as root but first when the user see the 2 processes

jameson
Contributor II

Something i do wrong as this does not work

#!/bin/zsh

dock_process=$(/usr/bin/pgrep -l "Dock")
finder_process=$(/usr/bin/pgrep -l "Finder")
until [[ "$dock_process" && "$finder_process" ]]; do
	/usr/local/jamf/bin/jamf policy
done

echo "Dock and Finder are both running"

jameson
Contributor II

And another additional question:

I created the  launchdaemon as pkg and placed it in pre-stage. The plist file is there, but it is not loaded when getting into the desktop first time the user sees it ... how to solve that

mm2270
Legendary Contributor III

A LaunchDaemon will not load automatically after being installed until its loaded by a command or a restart happens.

Since I'm guessing you'd rather avoid restarting for this, you can use launchctl to load the LaunchDaemon. There's more than one way to do this, syntax-wise. I still have luck using a command like this.

/bin/launchctl load /Library/LaunchDaemons/nameOfLaunchDaemon.plist

This also should work I think, and is often referred to as the more up to date syntax to use.

/bin/launchctl bootstrap system/<service-name>

As for the until loop not working, are you adding that into a script being called by your LaunchDaemon? Because the above script syntax can't be easily added into the ProgramArguments of a LaunchDaemon itself.

Try adding one of those kinds of commands to whatever it is that's deploying your LaunchDaemon to get it loaded right after it installs. If needed, you might need to add a postinstall script

bwoods
Valued Contributor

@jameson, below is a script that I use to create a luanch daemon for me and launch DEPNotify after enrollment. It should be able to help with your situation as well. I've commented out as much as I could, just let me know if you need help understanding something.

#!/bin/bash

# Create and load a LaunchDaemon to delay depnotify launch

	echo "<?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.depnotify</string> # Launch Damon name
		<key>UserName</key> # Use this to specify a username
		<string>root</string> # Here we are specifying the root user
		<key>ProgramArguments</key>
		<array>
			<string>/usr/local/jamf/bin/jamf</string> # This is the path to the jamf binary. I like to keep my scripts in the cloud so lines 15-18 are summoning my custom script policy.
			<string>policy</string>
			<string>-event</string>
			<string>jamfSetup</string>
			<string>-randomDelaySeconds</string>
			<string>25</string>
		</array>
		<key>RunAtLoad</key> # Run this daemon at load
		<true/>
		<key>StartInterval</key> # I want this to run every 10 seconds so I've added a Start Interval. The interger below is 10 for "10 Seconds"
		<integer>10</integer> 
	</dict>
	</plist>" > /tmp/depnotify.plist 
	
    sudo chown root:wheel /tmp/depnotify.plist
	sudo chmod 755 /tmp/depnotify.plist
	sudo launchctl load /tmp/depnotify.plist

exit 0

Captainamerica
Contributor II

So this is what you use in pre-stage, so right after the user see the desktop first time it should initiate depnotify ?

bwoods
Valued Contributor

@Captainamerica Yeah, It basically kicks off a chain of events. This launc hdaemon is deployed at enrollment, then kicks off my wait script, which waits until the desktop & dock are loaded. That script then initiates the depnotify GUI from the cloud. This would be much faster if I did it locally though. I just like the ability to edit quickly with the could.

jameson
Contributor II

Where in the script is stated that desktop and dock is loaded before anything is kicked in ? - May just be my scripting skills that is missing, as I also have been tried to find a solution for similar

bwoods
Valued Contributor

@jameson If you look at the Launch Daemon I've created, You'll see that the script isn't visible because I'm calling it with a policy that I've set up in Jamf Pro "sudo jamf policy -event jamfSetup" It's  just formatted differently in XML.

<string>/usr/local/jamf/bin/jamf</string> 
			<string>policy</string>
			<string>-event</string>
			<string>jamfSetup</string>

 

 

bwoods
Valued Contributor

The script below is the one being called by the Launch Daemon from my "jamfSetup" policy.

 

#!/bin/bash

# Determine the current user

currentUSER=$( scutil <<< "show State:/Users/ConsoleUser" | awk '/Name  && ! /loginwindow/ { print $3 }' )

jamfBinary=/usr/local/jamf/bin/jamf

# Determine if currentUser is logged in

if pgrep -x "Finder" \
&& pgrep -x "Dock" \
&& [ "$currentUSER" != "_mbsetupuser" ]; then

# Declare currentUser is logged in

echo "$currentUser is now logged in."
  
# Kill any installer process running

killall Installer
  
# Wait a few seconds

sleep 2
  
# Run the DEPNotify Starter Script  

$jamfBinary policy -event launchWizard

# Unload depnotify.plist

sudo launchctl unload /tmp/depnotify.plist

else

echo "The requirements above have not been met."

fi

exit 0
exit 1

 

Captainamerica
Contributor II

So the below script, how do you execute that in pre-stage ?.  Should I just add in in a pkg and add a postscript script inside this pkg or how ?

 

#!/bin/bash

# Create and load a LaunchDaemon to delay depnotify launch

	echo "<?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.depnotify</string> # Launch Damon name
		<key>UserName</key> # Use this to specify a username
		<string>root</string> # Here we are specifying the root user
		<key>ProgramArguments</key>
		<array>
			<string>/usr/local/jamf/bin/jamf</string> # This is the path to the jamf binary. I like to keep my scripts in the cloud so lines 15-18 are summoning my custom script policy.
			<string>policy</string>
			<string>-event</string>
			<string>jamfSetup</string>
			<string>-randomDelaySeconds</string>
			<string>25</string>
		</array>
		<key>RunAtLoad</key> # Run this daemon at load
		<true/>
		<key>StartInterval</key> # I want this to run every 10 seconds so I've added a Start Interval. The interger below is 10 for "10 Seconds"
		<integer>10</integer> 
	</dict>
	</plist>" > /tmp/depnotify.plist 
	
    sudo chown root:wheel /tmp/depnotify.plist
	sudo chmod 755 /tmp/depnotify.plist
	sudo launchctl load /tmp/depnotify.plist

exit 0

 

Captainamerica
Contributor II

OK - did a little troubleshooting. 

So the launchdaemon on client is running  after pre-stage (can also see the depnotifyplist in /tmp) and should trigger event "jamfSetup" 
But this for some reason does not seem to happen. If I go to terminal manually and do a sudo jamf policy -event jamfSetup the flow is working. 
So something does not seem to kick right in ?

Captainamerica
Contributor II

It seems the launchdaemon is not loaded correctly. If I do a sudo launchctl list com.depnotify is show on status "78" 

we looked up status 78 which mean "function not implemented"  So something in pre-stage package scripts seems to be not working, since it cannot load. Even tried a restart of the machine, but still the same status appear 

Download code Runner and test loading the daemon first. Then upload it to your server once you've verified that it works. I suggest removing the comments from the daemon. I usually don't run it with those comments.

bwoods
Valued Contributor
#!/bin/bash

# Create and load a LaunchDaemon to delay depnotify launch

	echo "<?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.ACME.depnotify</string>
		<key>UserName</key>
		<string>root</string>
		<key>ProgramArguments</key>
		<array>
			<string>/usr/local/jamf/bin/jamf</string>
			<string>policy</string>
			<string>-event</string>
			<string>jamfSetup</string>
		</array>
		<key>RunAtLoad</key>
		<true/>
		<key>StartInterval</key>
		<integer>4</integer>
	</dict>
	</plist>" > /tmp/depnotify.plist
	
    sudo chown root:wheel /tmp/depnotify.plist
	sudo chmod 755 /tmp/depnotify.plist
    sudo launchctl unload /tmp/depnotify.plist
	sudo launchctl load /tmp/depnotify.plist

exit 0

Captainamerica
Contributor II

Code is working fine in coderunner

The Pkg I create If I run this on a normal machine, the Launchdaemon is loaded as it should

If I take same package into pre-stage the issue happens. Launchdaemon somehow does not manage to load propably and keep status 78.
Is there any special trick to get a launchdaemon pkg loaded during pre-stage ? - the package works outside pre-stage and yes package is signed, as else the deamon plist would also not appear

bwoods
Valued Contributor

Hmmm...I'm not packaging my daemon script. I have a policy in Jamf Pro that triggers it at enrollment.

bwoods
Valued Contributor

also remove the "unload" near the bottom of the script. That is for Code Runner testing only.

Captainamerica
Contributor II

Yeah I know, that the script you posted does write the launchdaemon - but tried also to just create it as pkg, to see if that changes anything. But overall the either as your script or to create a PKG with a postinstall script that load the launchdaemon should give the same result.


Trying running it with an enrollment trigger without packaging it and see what happens. We can continue troubleshooting from there.

Captainamerica
Contributor II

Overall the issue is not enrollment trigger, but that the launchdaemon created is not running. So no matter what I put in there is not executed - not even if I try to do a restart afterwards the launchdaemon is not loaded by the system

Captainamerica
Contributor II

but if I do a manually launchdaemon load of the depnotify.plist it works

bwoods
Valued Contributor

Sounds like it wants you to run as the logged in user then.

Captainamerica
Contributor II

and of course if I try to manually install the package on a mac is also working. But if I install same package in pre-stage, the launchdaemon is not loaded, unless I do a manual load

bwoods
Valued Contributor

@Captainamerica  that sounds like an ownership/permissions issue. The script works from Jamf Pro because it runs all scripts as root. I'm not sure if that's the case for packaged post-install scripts.

Captainamerica
Contributor II

If I deploy the package through Jamf to a machine, the launchdaemon is installed and loaded and everything fine. But when same package is in pre-stage, it does not load automatically

bwoods
Valued Contributor

All I'm asking is that you try using the enrollment trigger. That's the best way to begin troubleshooting. You have to try different things to find the issue.

Captainamerica
Contributor II

So you mean the 

$jamfBinary policy -event launchWizard

bwoods
Valued Contributor

bwoods_0-1641419862704.png

 

Captainamerica
Contributor II

arh ok - I understand. But this enrollment trigger in jamf is not very stable - sometimes it works other times not is that I experience. But can give it a try

bwoods
Valued Contributor

Let me know how it goes, and I'll keep helping you troubleshoot.

Captainamerica
Contributor II

If I just add the launchdaemon script and enrollment complete trigger it works, as you asked for. I checked the file rights on the plist file to compare if there are somehow set different when it is going through pre-stage, but they are exactly the same


bwoods
Valued Contributor

What is your prestage workflow? 

Captainamerica
Contributor II

 

 

Captainamerica_0-1641814573317.png

Captainamerica_1-1641814615017.png

 

Captainamerica
Contributor II

@bwoods Can you try and show you pre-stage setup in jamf. 
Do you have more packages in pre-stage or just one package with both jamf connect and the launchdaemon script ?

Even Low level - can you show how the package looks like if you show a composer view of the pkg ? Something is strange that the launchdaemon also for me cannot start 

bwoods
Valued Contributor

@Captainamerica I install two packages at enrollment:

1. Automated Device Enrollment Starter

a. contains a preinstall script for rosetta for M1 hardware

b. DEPNotify

c. logos for DEPNotify.

 

2. A Location Services Package.

a. This contains a post install script that enables location services automatically. This could have been in the ADE starter but I already had it packaged in Jamf Pro. 

 

I install Jamf Connect with the DEPNotify GUI due to MFA policies at my organization. For now, I have my Desktop team create the accounts manually. But I have tested with Jamf Connect as well and it still works.

 

bwoods
Valued Contributor

bwoods_0-1642083498733.png

 

bwoods
Valued Contributor

bwoods_1-1642083523358.png