Unload/Load Launch Agent run as user?

macmanmk
Contributor

Is it possible to unload or load a Launch Agent being run as a user? I know all scripts are executed as root. We have an auto-save utility that is run via launch agent at ~/Library/LauncheAgents and we need to unload it to stop it and then load it when ready to start it back up.

I tried using the following script and although it shows that it runs successfully, it doesn't appear to unload the agent. Can anyone point out if the script is flawed or if what we are trying to do just isn't possible?

#!/bin/bash

## Get logged in user and UID
loggedInUser=$(stat -f%Su /dev/console)
loggedInUID=$(id -u $loggedInUser)

## Put the name of the process to call on here. Run "ps axc" to look for the process name
SaveMeProcess="savemed"
## Put the LaunchAgent plist path and name here
SaveMePlist="/Library/LaunchAgents/com.chapman.SaveMe.plist"

if [ "$loggedInUser" != "root" ]; then
    echo "A user is logged in. Checking for agent process..."
    ## Check for agent as user
    FCProcCheck=$(/bin/launchctl asuser $loggedInUID sudo -iu $loggedInUser ps axc | grep "SaveMeProcess" 2>&1 >/dev/null; echo $?)
    if [ "$FCProcCheck" != 0 ]; then
        echo "Agent is not running. Reloading..."
        /bin/launchctl asuser $loggedInUID /bin/launchctl unload "$SaveMePlist"
    else
        echo "Agent process is running. Nothing to do."
        exit 0
    fi
else
    echo "No-one logged in. Cannot check on process."
    exit 0
fi
5 REPLIES 5

BOBW
Contributor II

HI,
Is it because you are trying to run the launchAgent from /Library/LaunchAgent as the user? User LaunchAgents have to be ran from the ~/Library/LaunchAgents?

What happens when you just run these one line at a time?

especially the line:
/bin/launchctl asuser $loggedInUID /bin/launchctl unload "$SaveMePlist"
change the variables to full paths and manually enter the logged in user ID

macmanmk
Contributor

Thanks @BOBW. That's definitely the issue. The file definitely resides in the user-level LaunchAgents directory. But how do I call the user-level directory in the script? If I just use the tilde, I get the following output when run with "testacct" as the logged in user...

/Users/testacct/~/Library/LaunchAgents/com.chapman.SaveMe.plist: No such file or directory

mschroder
Valued Contributor

@macmanmk But you already have $loggedInUser, so the path you are looking for should be /Users/"$loggedInUser"/Library/LaunchAgents/com.chapman.SaveMe.plist, shouldn't it?

BOBW
Contributor II

@macmanmk Exactly what @mschroder said.

I think the best way to check your path is correct is to drag the file into a clean terminal window, this will enter the path for you. It will even put in the backslashes to comment out the spaces, just copy this into your script.

If you are using the inverted commas such as " then make sure you remove the backslashes

BPM
New Contributor

hi,

loggedInUser=$(stat -f%Su /dev/console) gives the username. However the username is not always equal to the name of the users homedir.

Good news is that you already have the UID, so you can add something like:

loggedInUserHome=$(dscacheutil -q user | grep -A 3 -B 2 $loggedInUID | grep dir | awk '{print $2}')

to your script and $loggedInUserHome should be the correct homedir.

edit from:

SaveMePlist="/Library/LaunchAgents/com.chapman.SaveMe.plist"

to

SaveMePlist="$loggedInUserHome/Library/LaunchAgents/com.chapman.SaveMe.plist"

and grep "SaveMeProcess" to grep "$SaveMeProcess"

all:

#!/bin/bash

## Get logged in user and UID
loggedInUser=$(stat -f%Su /dev/console)
loggedInUID=$(id -u $loggedInUser)
loggedInUserHome=$(dscacheutil -q user | grep -A 3 -B 2 $loggedInUID | grep dir | awk '{print $2}')

## Put the name of the process to call on here. Run "ps axc" to look for the process name
SaveMeProcess="savemed"
## Put the LaunchAgent plist path and name here
SaveMePlist="$loggedInUserHome/Library/LaunchAgents/com.chapman.SaveMe.plist"

if [ "$loggedInUser" != "root" ]; then
    echo "A user is logged in. Checking for agent process..."
    ## Check for agent as user
    FCProcCheck=$(/bin/launchctl asuser $loggedInUID sudo -iu $loggedInUser ps axc | grep "$SaveMeProcess" 2>&1 >/dev/null; echo $?)
    if [ "$FCProcCheck" != 0 ]; then
        echo "Agent is not running. Reloading..."
        /bin/launchctl asuser $loggedInUID /bin/launchctl unload "$SaveMePlist"
    else
        echo "Agent process is running. Nothing to do."
        exit 0
    fi
else
    echo "No-one logged in. Cannot check on process."
    exit 0
fi