Run Script with Launchd at Login

Discussion in 'Mac Programming' started by Ash9414, Mar 2, 2017.

  1. Ash9414, Mar 2, 2017
    Last edited: Mar 2, 2017

    Ash9414 macrumors 6502

    Joined:
    Apr 25, 2010
    Location:
    United Kingdom
    #1
    I'm attempting to setup a Launch Agent that will run a simple shell script to mount a FUSE drive at login. I have written a .plist file and moved it into the ~/Library/LaunchAgents/ directory (shown below). Both the .plist and the shell script have permissions of 755. I am able to use the "launchctl load ~/Library/LaunchAgents/com.user.loginscript.plist" command to load the .plist, such that it then appears when I do "launchctl list". However, when I logout and then log back in again, I know the shell script hasn't run because the drive hasn't been mounted. I can confirm the script itself is probably not the problem, as it behaves correctly when run through Terminal. Does anyone have any ideas as to what may be preventing the Launch Agent from working as desired?

    Thanks in advance.

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>com.user.loginscript</string>
        <key>ProgramArguments</key>
        <array>
            <string>/bin/sh</string>
            <string>/Path/To/Script.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>KeepAlive</key>
        <dict>
            <key>SuccessfulExit</key>
            <false/>
        </dict>
    </dict>
    </plist>
     
  2. jasnw macrumors 6502

    Joined:
    Nov 15, 2013
    Location:
    Seattle Area (NOT! Microsoft)
    #2
    Have you tried directing stdout and stderr to a log file using the StandardOutPath and StandardErrorPath keys? That might give you some clues. I suspect you're going to find issues with macOS and FUSE not playing together well.
     
  3. kryten2 macrumors 6502a

    Joined:
    Mar 17, 2012
    Location:
    Belgium
    #3
    You can also instruct launchd to temporarily increase the debug level of its logging. See the link for more information. There's no need to logout and then log back in again as you're using the
    RunAtLoad key. Your job should run when using the launchctl load command. Are there any permissions errors when loading the job? What is the last exit status of the job when you run launchctl list command?
    Did you try launchctl start?

    Info : https://developer.apple.com/library...bs.html#//apple_ref/doc/uid/10000172i-SW7-SW5 - https://developer.apple.com/legacy/...nchctl.1.html#//apple_ref/doc/man/1/launchctl
     
  4. Ash9414 thread starter macrumors 6502

    Joined:
    Apr 25, 2010
    Location:
    United Kingdom
    #4

    So I've just altered the .plist to include the StandardOutPath, StandardErrorPath, and Debug keys. I get a .log file created at the path that I specified, but it doesn't contain anything.

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>com.user.loginscript</string>
        <key>ProgramArguments</key>
        <array>
            <string>/bin/sh</string>
            <string>/Path/To/Script.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>StandardOutPath</key>
        <string>/Path/To/Log.log</string>
        <key>StandardErrorPath</key>
        <string>/Path/To/Log.log</string>
        <key>Debug</key>
        <true/>
    </dict>
    </plist>

    I have also tried to run "launchctl start com.user.loginscript", but that makes no difference as it seems like Launchd is already trying to run the .plist. There are no errors shown on the command line when I either load or start it. The exit status when I run the "launchctl list" command is 0.
     
  5. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #5
    There's a simpler way to do this than launchd.

    Simply make an Automator workflow with a single Run Shell Script action in it. Put this in that action:
    Code:
    /Path/To/Script.sh
    
    In Automator, save it as an application.

    Next, run System Preferences, and follow the instructions here to add the newly saved application to the list of items to Open at Login:
    https://support.apple.com/kb/PH21985?locale=en_US


    The advantages of this approach over launchd:
    1. Easier to add and remove as a login item.
    2. You can redirect stdout & stderr in the Run Shell Script action using ordinary shell syntax.
    3. You can add other diagnostics in the Run Shell Script action (printenv, sleep, etc.).
    4. You can test the Automator application at any time just by double-clicking it.
    5. No fiddly launchd or launchctl dependencies.
     
  6. Ash9414 thread starter macrumors 6502

    Joined:
    Apr 25, 2010
    Location:
    United Kingdom
    #6

    Thanks for your response!

    I did come across using Automator as an alternative method to run a shell script at login, but other people had suggested that perhaps using Launchd was a cleaner and more capable solution. Anyway, I have gone through the steps you posted and everything seems to be working as desired now, so thanks for your help! :)
     
  7. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #7
    Glad you got it working.

    There's nothing cleaner about launchd in this specific case. It's more complex, less predictable, and is overkill for what needs to be accomplished.

    I mentioned "fiddly dependencies" above, so if you ever venture into launchd's territory again, you should read these:
    https://developer.apple.com/library...al/BPSystemStartup/Chapters/Introduction.html
    https://developer.apple.com/library/content/technotes/tn2083/_index.html

    Google search terms: mac daemons guide

    While launchd is powerful and flexible, it's also arcane and perplexing. If it offers a feature you absolutely need, such as launching on a timed schedule or triggered by a port or file change, then it's worth digging into it. Since all you needed was to run something once at login, you're much better off using ordinary Login Items.
     

Share This Page