KraigM / HomeBridgeController

Provides a simplified UI for controlling your HomeBridge
88 stars 7 forks source link

Need a way to auto restart homebridge after modification #16

Closed KraigM closed 8 years ago

KraigM commented 8 years ago

After we upload a new config or install a new plugin, we need a way to auto restart (or restart on demand).

KraigM commented 8 years ago

This was mentioned on the main readme and there has also been some side bar discussions on #6 but I thought I should go ahead and create this so others can throw out their ideas

johnschult commented 8 years ago

Since homebridge might be started on various OSs in various ways, what about adding a restart command to the platform in .homebridge/config.json? For example:

{
  "platform": "HomeBridgeControllerLink",
  "restartCommand": "sudo service homebridge restart"
}

Then everyone could set it to whatever they use to manage homebridge. I suppose homebridge-controllerlink could just use child_process.exec to run the restartCommand.

KraigM commented 8 years ago

@johnschult Sorry I didn't actually respond to you but I saw this and I think that is a great idea. We will have to figure out a way to stop the running one first before restarting (due to port conflicts).

To build on that, we could create a script (similar to bin/homebridge) that actually manages the restart when triggered by the plugin. It should just involve adding another command to the beginning of your current startup script (similar to supervisor but more tailored to homebridge and HomeBridgeController)

luisiam commented 8 years ago

@KraigM How about separating the restartCommand to a stopCommand and startCommand?

KraigM commented 8 years ago

Still begs the question, how do will that work? As far as I know (node is not my forte so I could be wrong), the only way to start a process from within node is a child process, which means the calling process would not be able to end without killing the child. And without killing the calling process, the child wouldn't be able to start (since the previous run would still be running).

Another thing is that if it crashes, there is nothing to restart it. But that isn't something homebridge controller necessarily needs to do (just a nice to have).

Anyone have any magic voodoo work around that they know of? Or am I just totally missing something obvious :smile: ?

johnschult commented 8 years ago

It will work. The idea is to use child_process.exec to run scripts, not to spawn a child process and keep it around. No magic voodoo, I promise :smiling_imp:

Here is a real-world example that I ran on my machine:

$ mysql.server stop
$ mysql.server status
 ERROR! MySQL is not running
$ node
> const exec = require('child_process').exec
> exec('/usr/local/bin/mysql.server start')
> process.exit()
$ mysql.server status
 SUCCESS! MySQL running (21065)
KraigM commented 8 years ago

@johnschult Good point, but mysql.server was designed for that kind of stuff (i.e. no tty). But based on your suggestion, I found out that node has a child process spawn with detached option.

That however still does not cover the issue of the active process has a listener on the same port that the new process will want. Right now the only way to shutdown homebridge's internal server (buried behind 8 levels of inception) is to kill the process. But we obviously start a new process after we kill the current one. If we start it before we kill the current one, then when it reaches the point where it tries to listen to the port, the orig process may not be closed yet (chicken-egg).

KraigM commented 8 years ago

Im digging through several options right now:

Have any suggestions to mitigate/implement any of these? Any other suggestions?

KraigM commented 8 years ago

Another possible option:

KraigM commented 8 years ago

@johnschult Ok I did get this to work (huzzah)

log('restarting...');
var args = process.argv.slice();
var cmd = args.shift();
ChildProcess.spawn(cmd, args, {
    detached: true,
    stdio: 'ignore'
});
process.exit(0);

With that, it will reuse the correct node, all the command line args, environment variables, and what not. Only issue is that it becomes a rogue process (if you will). If you started it from terminal, it will lose its connection and it will not output to the terminal anymore. Even if you redirected the output to a file, it will stop redirecting to that file.

This is bc if I piped, inherited, or whatever, it would auto quit as soon as the main process quit when using spawn. If I use exec, it does not detach. The only way around the custom redirects that I can see would be for the user to write a script that detaches and then redirects. We could instead just make the redirects a config option because it does work if I specify the redirect file. That all being said, as of 0.5.0, log capturing is already built into homebridge-controllerlink so I don't know if its necessary.

Thoughts? Is there any reason you guys want to specify your own command instead of the auto solution above?

KraigM commented 8 years ago

For now (unless you guys speak up :smile:) I am going to stick with restarting using the original command. I am also going to leave it as a manual restart (for now), but I prompt to restart after installations. I didn't however prompt for it on save/upload (thought it might get annoying).

KraigM commented 8 years ago

What I stated above is completed and will be in the next release 0.6.0.