I am attempting to set up a .plist
file for use with launchctl
on OSX. When run from the command line (not using launchctl
), our application is executed as:
/path/to/ourapp
... and to terminate our application, we type:
/path/to/ourapp -k
... which causes the new instance of ourapp
to properly kill the previous instance that is running.
Now I set up a .plist
file to control execution of the application via launchctl
, as follows:
// start.plist
<dict>
<key>Disabled</key>
<false/>
<key>Label</key>
<string>ourapp</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/ourapp</string>
</array>
<key>OnDemand</key>
<false/>
<key>UserName</key>
<string>daniel347x</string>
<key>SHAuthorizationRight</key>
<string>system.preferences</string>
</dict>
... and I execute it at the command line, as follows:
launchctl load /path/to/start.plist
This works successfully to launch the application.
Unfortunately, when creating a stop.plist
, as follows (the only difference is the addition of the -k
argument):
// stop.plist
<dict>
<key>Disabled</key>
<false/>
<key>Label</key>
<string>ourapp</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/ourapp</string>
<string>-k</string> // <-- only difference is adding this argument
</array>
<key>OnDemand</key>
<false/>
<key>UserName</key>
<string>daniel347x</string>
<key>SHAuthorizationRight</key>
<string>system.preferences</string>
</dict>
... and executing via
launchctl unload /path/to/stop.plist
... the application does NOT terminate ... therefore, it seems that when using launchctl
, the application is not being executed equivalently to
/path/to/ourapp -k
Can someone tell me what launchctl unload
is really doing - i.e. is it calling the application from the command line with the given arguments, or not - and what I can do to get my stop.plist
to work when using launchctl unload
, given whatever it is doing?
No, "launchctl unload" on OSX does not pass "ProgramArguments" to the target application. It removes the plist from the ones that launchd is running.
I'm not sure you are using launchctl and launchd the way it was designed, but try:
launchctl load /path/to/stop.plist
The launchctl command is used to control which plists launchd runs at any given time. When you issue:
launchctl load /path/to/start.plist
the plist is loaded into launchd and your "ourapp" is trigged. A critical point is that unless "ourapp" unloads the start.plist, it will still be running in launchd. You can check this by viewing the output from:
launchctl list
The reason your call to unload the stop.plist didn't have any effect is that it was never loaded into launchd to begin with. To be able to stop it, you must first start it with:
launchctl load /path/to/stop.plist
The trick with this is that once you do this, both your start.plist and stop.plist will be running. Obviously, I haven't tested your app/setup, but this could cause weird behavior. Also, I'm not sure what running the "load" again on your start.plist would do since it would already be running.
Form what you've described here, it looks like launchd and launchctl might not be the best approach. If you want to stick with it, I think you would need to add system calls into your "ourapp" so that when it gets issued the kill command it also unloads both the start and the stop plist. Or, write a proxy script that unloads the plists and then calls your "ourapp -k". That way, the next time you use "launchctl load /path/to/start.plist" you won't be trying to start something that's already running.
One other note. You might have just been using the "ourapp" as place holders, but it's worth pointing out that you probably want to use unique Label names. If nothing else, it'll help you keep track of them with "launchctl list". I don't know if launchd itself would have an issue with duplicate names, but it seems safest to avoid the possibility.