Posted on 08-06-2015 02:41 PM
Hello,
I am having difficulty figuring out if there is a way to push out a LaunchAgent to multiple machines at the same time. I have a .plist file that I would like to have put into '/Library/LaunchAgents' for all of our machines in our environment.
Does the JSS or Casper Remote provide a way to place a .plist file into '/Library/LaunchAgents' for multiple machines? It would be great if I can avoid placing the .plist file into this location manually (one-by-one).
Thank you,
-Alex H.
Solved! Go to Solution.
Posted on 08-06-2015 03:08 PM
Hey @haalx790
Package the Launch Agent using Composer and deploy it via the JSS, Casper Remote or ARD.
Make sure to include this as post flight script to set some permissions and load the agent. Right click on "Scripts", click on "Shell Script" and "post flight".
#!/bin/bash
chown root "/Library/LaunchAgents/NAMEOF.plist"
chmod 644 "/Library/LaunchAgents/NAMEOF.plist"
launchctl load -w "/Library/LaunchAgents/NAMEOF.plist"
Example of where to put the preflight script:
Good luck!
Posted on 08-06-2015 03:08 PM
Hey @haalx790
Package the Launch Agent using Composer and deploy it via the JSS, Casper Remote or ARD.
Make sure to include this as post flight script to set some permissions and load the agent. Right click on "Scripts", click on "Shell Script" and "post flight".
#!/bin/bash
chown root "/Library/LaunchAgents/NAMEOF.plist"
chmod 644 "/Library/LaunchAgents/NAMEOF.plist"
launchctl load -w "/Library/LaunchAgents/NAMEOF.plist"
Example of where to put the preflight script:
Good luck!
Posted on 08-06-2015 03:09 PM
Yes, just package it up in Composer the same way you would do with any item you're looking to deploy. I recommend a package installer (.pkg), but you could in theory use a .dmg format as well.
The only other consideration would be if you want to load the LaunchAgent right away after its installed, or wait for it to load naturally at the next login. Getting LaunchDaemons to load via postinstall scripts in a pkg is easy. LaunchAgents take a little more work since they have to load as the user, not as root.
Posted on 08-06-2015 04:21 PM
I find it's easier to simply create a script on your JSS that echoes that plist out to the /Library/LaunchAgents folder, then that same script can load it if you'd like. No need to mess with packaging it.
Posted on 08-06-2015 10:08 PM
+1
Posted on 08-07-2015 05:41 AM
@alexjdale would you mind sharing an example of the solution you recommended above? It's not a method I am familiar with. I'm familiar with the way @mm2270 suggested. It's nice to have options though.
Posted on 08-07-2015 07:21 AM
@mpermann I believe he's talking about this: https://en.wikipedia.org/wiki/Here_document
Two examples from @rtrouton 's blog:
https://derflounder.wordpress.com/2011/09/23/setting-multiple-network-time-servers-from-the-command-...
#!/bin/sh
/bin/cat > /etc/ntp.conf << 'NEW_NTP_CONF'
server ns0.time.server
server ns1.time.server
server time.apple.com
NEW_NTP_CONF
And from the postinstall example here:
https://derflounder.wordpress.com/2015/02/26/deploying-sophos-enterprise-anti-virus-for-mac-9-2-x/
#!/bin/sh
/bin/cat > "/Library/Preferences/com.sophos.sau.plist" << 'SOPHOS_CONFIG'
<?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>LastUpdated</key>
<string>February 25, 2015 at 9:17:42 AM EST</string>
<key>OverrideCredentialsForSaas</key>
<integer>0</integer>
<key>PrimaryServerProxy</key>
<integer>0</integer>
<key>PrimaryServerProxyPort</key>
<integer>0</integer>
<key>PrimaryServerProxyURL</key>
<string></string>
<key>PrimaryServerType</key>
<integer>2</integer>
<key>PrimaryServerURL</key>
<string>smb://sophos_enterprise_server_name_goes_here/SophosUpdate/CIDs/S000/ESCOSX</string>
<key>SecondaryServer</key>
<true/>
<key>SecondaryServerProxy</key>
<integer>0</integer>
<key>SecondaryServerProxyPort</key>
<integer>0</integer>
<key>SecondaryServerProxyURL</key>
<string></string>
<key>SecondaryServerType</key>
<integer>0</integer>
<key>SecondaryServerURL</key>
<string></string>
<key>UpdateFrequency</key>
<integer>1</integer>
<key>UpdateInterval</key>
<integer>10</integer>
<key>UpdateLogIntoFile</key>
<true/>
<key>UpdateLogIntoSyslog</key>
<false/>
<key>UpdateOnConnection</key>
<false/>
<key>UpdateUnits</key>
<integer>1</integer>
</dict>
</plist>
SOPHOS_CONFIG
Posted on 08-07-2015 07:28 AM
Echoing out a launchd from a script is actually a good method. I use that often in my scripts since it allows you to actually create dynamic LaunchDaemons and LaunchAgents that can have custom information based on the Mac the script is running it on if needed.
However, I wouldn't recommend that method to start for someone who is new to using launchd jobs, just because there are several gotchas to watch out for that, if, unaware of them can cause a massive amount of frustration. And sometimes the syntax needing to be used in the plist files isn't exactly intuitive. For someone new to all this, I'd recommend first starting out making them in an application like LaunchControl or Lingon, to gain an understanding of how they are created. Once comfortable with them, then yes, its good to explore making them on your own via scripts.
Also, simply echoing out the contents to a file isn't enough. You need to make sure the owner:group and permissions on the file are correct after its created or the OS won't load it.
chown root:wheel /Library/LaunchAgents/com.org.someexample.plist
chmod 644 /Library/LaunchAgents/com.org.someexample.plist
Posted on 08-07-2015 07:43 AM
Posted on 08-07-2015 08:48 AM
I actually just use echo. When running from the JSS, I haven't had to change ownership or permissions in my experience, it just works.
https://jamfnation.jamfsoftware.com/discussion.html?id=14940
Posted on 08-07-2015 08:57 AM
which probably makes sense since the JSS is doing things as root so it gets set to root:wheel by default, you have just been lucky that the default umask did not make the file group writable. That would cause problems.
Posted on 08-07-2015 10:57 AM
I use this for loading LaunchAgents as the user,
with much appreciated help from @mm2270 + @yr_joelbruner
#!/bin/sh
loggedInUser=$( stat -f%Su /dev/console )
loggedInPID=$( ps -axj | awk "/^$loggedInUser/ && /Dock.app/ {print $2;exit}" )
(/bin/launchctl bsexec "${loggedInPID}" sudo -iu "${loggedInUser}" "launchctl load /Library/LaunchAgents/your.launchagent.job.plist")
Posted on 08-07-2015 10:58 AM
It is somewhat unfortunate that you just figured this out. seems to not work very well in public beta versions of some other OS that will be coming soon...
Posted on 08-07-2015 02:19 PM
Thank you all for your help! I was able to add my .plist file to the 'Sources' area of Composer, add the post flight shell script and then build it as a package. I then deployed the package out through Casper Remote and it worked! The third-party app that I wanted to launch on user login is launching like I wanted (it seems to be launching for all users who log in also which is awesome). Thank you again everyone!
Posted on 03-02-2016 05:21 AM
@May I have a similar situation and was able to use asuser to run my 10.10 and 10.11 LaunchAgents but I'm trying to use bsexec to handle by 10.9 and older and I'm running into an error.
I have the syntax correct as far as I can tell but when I run the command I get:
sudo: unable to execute /bin/bash: Bad address
launchctl bsexec failed: No such file or directory
Have you encountered this before?
UPDATE:
So I do have the syntax correct, I've noticed that if I run the command several times it eventually works, usually on the second or third run so I think sytax is good, but I cant explain why it doesnt consistently work (when it does fail it gets the same error as above).
Posted on 03-02-2016 07:20 AM
@jmb03012 From some other advice, I stopped using bsexec and now use sudo -u, like this:
# Get logged in user account, use lpadmin to add copier as user
loggedInUser=$( stat -f%Su /dev/console )
sudo -u $loggedInUser /usr/sbin/lpadmin -p PrinterName -L PrinterLocation -E -o printer-is-shared=false -v smb://server/PrinterName -P /Library/Printers/PPDs/Contents/Resources/PrinterDriver.gz -o auth-info-required=negotiate
sudo -u $loggedInUser lpoptions -d PrinterName
Posted on 03-02-2016 07:36 AM
@rcastorani For 10.10 and 10.11 using sudo -u will usually cause issues, but I had thought also that you could still use it 10.9 and older but when I try I am running into a different error:
sudo -u geid_mac_dev launchctl unload /Library/LaunchAgents/com.bloomberg.BNotifier.plist
Could not open job overrides database at: /private/var/db/launchd.db/com.apple.launchd.peruser.0/overrides.plist: 13: Permission denied
launchctl: CFURLCreateDataAndPropertiesFromResource(/Library/LaunchAgents/com.bloomberg.BNotifier.plist) failed: -10
launchctl: no plist was returned for: /Library/LaunchAgents/com.bloomberg.BNotifier.plist
launchctl: no plist was returned for: /Library/LaunchAgents/com.bloomberg.BNotifier.plist
nothing found to unload
Posted on 03-28-2018 07:04 AM
A little late to the game, I had the same requirement as @jmb03012, @rcastorani and @May - load the LaunchAgent as the user. The bsexec command with PID fails on SIP enabled devices, but launchctl 2.0 offers the following syntax to load the LaunchAgent as the user.
#!/bin/sh
#Get Username and UID
user=`ls -la /dev/console | cut -d " " -f 4`
uid=`id -u $user`
echo "User: $user"
echo "UID: $uid"
PLIST_NAME="com.acme.coyote"
PLIST_FILE=/Users/$user/Library/LaunchAgents/$PLIST_NAME.plist
echo "Plist Name: $PLIST_NAME"
echo "Plist File: $PLIST_FILE"
# Create your plist file here...
#cat <<EOF > $PLIST_FILE
#<?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>$PLIST_NAME</string>
#...
#</dict>
#</plist>
#EOF
echo "Plist file created"
#Unload
launchctl print gui/$uid/$PLIST_NAME &>/dev/null && launchctl bootout gui/$uid $PLIST_FILE
echo "Unloaded plist"
#Load
launchctl bootstrap gui/$uid $PLIST_FILE
echo "Loaded plist"
More info on launchctl 2.0 at https://babodee.wordpress.com/2016/04/09/launchctl-2-0-syntax/
Hope this helps a random person in the future.
Posted on 12-02-2020 09:31 AM
Is that the correct syntax for a launchdaemon? Because for me it is not running, when I deploy it. The launchdaemon is loaded, but the script won't be executed.
#!/bin/bash
#### Create a script ####
cat << EOF > /Library/Folder/myScript.sh
#!/bin/bash
echo "Here is my script"
EOF
#### Create a plist file ####
cat << EOF > /Library/LaunchDaemons/com.jamf.launchdaemon.plist
<?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>KeepAlive</key>
<true/>
<key>Label</key>
<string>com.jamf.launchdaemon</string>
<key>ProgramArguments</key>
<array>
<string>sh</string>
<string>/Library/Folder/myScript.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
EOF
#### Set permissions for both files ####
chmod 644 /Library/LaunchDaemons/com.jamf.launchdaemon.plist
chown root:wheel /Library/LaunchDaemons/com.jamf.launchdaemon.plist
chmod 755 /Library/Folder/myScript.sh
chown root:wheel /Library/Folder/myScript.sh
#### Load launchdaemon ####
launchctl load /Library/LaunchDaemons/com.jamf.launchdaemon.plist
Posted on 12-02-2020 11:17 AM
@slang I don't know if it's at all related, but since you're already making the script executable, you don't need to have the <string>sh</string>
line in the LaunchDaemon, since just calling the script should execute it fine. This is coming from my own experience in working with LaunchDaemons and LaunchAgents. I would try removing that from the ProgramArguments array and try it again to see if it works.
Also, was the script you're creating in what you posted above just an example or is that the script you're testing with? I ask because I'm wondering how you confirm if it's working or not working since all it's doing is echoing a line to stdout. To really test it, I would have the script output to a local file maybe.
Posted on 12-02-2020 11:41 AM
No, this is not the original script. I just wanted to understand, if the syntax is fine.
In general i have a package with a script, a plist file and a postinstall script. All together works fine, when I deploy it via a package. But with this approach if using a simple script, it does not work so far. And I just want to understand, what the difference is :)