Chris Cioffi1

Q: El Cap launchctl won't re-read plist after editing

I'm trying to learn about launchd and the plist files that control it.  I have a simple script that echoes the current time to a file as my test program.

 

I originally used the StartInterval to run the script every 60 seconds.  Then I ran launchctl unload -F <plist> to unload the file and updated the plist to use StartCalendarInterval every 3 minutes.  No matter what I do (including rebooting!) launchd seems to have that original file cached and it persists in running every minute. 

 

I've tried to run launchctl uncache, but that says that it's not implemented.

 

The file is in ~/Library/LaunchAgents, so we're not talking about a system file.

 

Is it not possible to clear the cache?  Do I need to rename the file and or label in the plist anytime I want to change it?

Posted on Dec 28, 2015 2:37 PM

Close

Q: El Cap launchctl won't re-read plist after editing

  • All replies
  • Helpful answers

  • by twtwtw,

    twtwtw twtwtw Dec 28, 2015 3:11 PM in response to Chris Cioffi1
    Level 5 (4,935 points)
    Dec 28, 2015 3:11 PM in response to Chris Cioffi1

    launchctl has (apparently) undergone a significant rewrite; load and unload are now considered 'legacy' commands, with the warning that they may not be implemented.

     

    Check the man page. I think the commands you want now are enable/disable, but I haven't read it over thoroughly yet.

  • by Chris Cioffi1,

    Chris Cioffi1 Chris Cioffi1 Dec 30, 2015 3:01 PM in response to twtwtw
    Level 1 (0 points)
    Dec 30, 2015 3:01 PM in response to twtwtw

    Ok, so I've been reading the man page for launchctl, and I'm having no lunch at all getting my plist to run with the new commands.

     

    After a lot of other searching and trying crap out, I found that

    Launchctl enable user/$UID/<pretty much anything at all here>

    Will at least run without error.  Whee!

     

    However, the command doesn't actually seem to do anything.

     

    Launchctl bootstrap andlaunchctl kickstart fail no matter what command line options I use.

     

    launchctl bootstrap user/$UID ./<plist filename>

    launchctl bootstrap user/$uid <plist filename (not path) or label inside plist>

    launchctl bootstrap user <plist filename (not path) or label inside plist>

    launchctl kickstart -k launchctl kickstart -k user/launchctl kickstart -k user/$UID/launchctl kickstart user/$UID/launchctl kickstart user/

    I really, really wish I could video tape/screen capture this whole process and force the developer to watch what I'm going through before every line of code they type.  Maybe, just maybe, they might understand that what they think of as clear and obvious is far, far, far from it for people other than them.

  • by twtwtw,

    twtwtw twtwtw Dec 31, 2015 10:50 AM in response to Chris Cioffi1
    Level 5 (4,935 points)
    Dec 31, 2015 10:50 AM in response to Chris Cioffi1

    Well first, just so it's said, you can always use the old-fashioned system: log out and log back in (or restart if you're dealing with a system level daemon). launchctl is an interface for developers, not a necessary part of the launchd system.

     

    That being said, here are my best guesses at the moment, as I'm playing with it:

     

    • bootstrap and bootout seem to be the rough equivalents of the old load and unload commands. They load a plist or service into the launchd cache and set it up as a job so that launchd starts watching for demand.
    • kickstart seems to be the equivalent of start command. It creates an artificial demand so that a loaded job is triggered immediately (if -k is specified, it kills any running instance and restarts it).
    • enable/disable seem to have the same purpose as the enabled/disabled key in a plist file

     

    The rest I'll skip for the moment because they seem to be developer tricks: For instance, uncache apparently forces launchd to bypass its own cache and read directly from disk so that changes register immediately, kill saves you from having to kill a process from outside launchd, attach adds a debugger...

     

    The tricky part is figuring out the specifiers that indicate which job, plist, or service is being targeted by launchctl. Obviously Apple was trying to generalize launchctl so that it could handle more kinds of services, more flexibly, but they haven't documented well. My best guess at the moment is that you can either use paths or general domains with identifiers. So for instance, if you have a plist with the file name 'test.plist' in the user launchagents folder, and it has the identifying label 'user.launchd.test', then you can use either of the following:

     

    • launchctl bootstrap /user/<yourid>/launchagents/test.plist
    • launchctl bootstrap user/<yourid>/user.launchd.test

     

    More later today when I get a chance to experiment some.

  • by twtwtw,

    twtwtw twtwtw Dec 31, 2015 1:15 PM in response to Chris Cioffi1
    Level 5 (4,935 points)
    Dec 31, 2015 1:15 PM in response to Chris Cioffi1

    You know, I just double-checked, and the load command seems to work fine, so I think you can stick with the legacy commands and avoid the new commands until apple spits out some better documentation.

     

    Going back to your original question, perhaps you should use the remove command rather than the unload command.  In other words:

     

    launchctl remove <joblabel>

     

    Where joblabel is whatever you put in the 'label' key of the plist. remove should clear it out of launchd's job cache. unload ought to do the same, but if I'm reading the docs correctly unload may fail silently unless you've made an obvious syntax error.