// configurePath sends the client's PATH to the service. func configurePath(g *libkb.GlobalContext, cl *libcmdline.CommandLine) error { if cl.IsService() { // this only runs on the client return nil } return client.SendPath(g) }
// AutoFork? Standalone? ClientServer? Brew service? This function deals with the // various run configurations that we can run in. func configureProcesses(g *libkb.GlobalContext, cl *libcmdline.CommandLine, cmd *libcmdline.Command) (err error) { g.Log.Debug("+ configureProcesses") defer func() { g.Log.Debug("- configureProcesses -> %v", err) }() // On Linux, the service configures its own autostart file. Otherwise, no // need to configure if we're a service. if cl.IsService() { g.Log.Debug("| in configureProcesses, is service") if runtime.GOOS == "linux" { g.Log.Debug("| calling AutoInstall") _, err := install.AutoInstall(g, "", false) if err != nil { return err } } return nil } // Start the server on the other end, possibly. // There are two cases in which we do this: (1) we want // a local loopback server in standalone mode; (2) we // need to "autofork" it. Do at most one of these // operations. if g.Env.GetStandalone() { if cl.IsNoStandalone() { err = fmt.Errorf("Can't run command in standalone mode") return err } err := service.NewService(g, false /* isDaemon */).StartLoopbackServer() if err != nil { if pflerr, ok := err.(libkb.PIDFileLockError); ok { err = fmt.Errorf("Can't run in standalone mode with a service running (see %q)", pflerr.Filename) return err } } return err } // After this point, we need to provide a remote logging story if necessary // If this command specifically asks not to be forked, then we are done in this // function. This sort of thing is true for the `ctl` commands and also the `version` // command. fc := cl.GetForkCmd() if fc == libcmdline.NoFork { return configureLogging(g, cl) } // If this command warrants an autofork, do it now. var newProc bool if fc == libcmdline.ForceFork || g.Env.GetAutoFork() { newProc, err = client.AutoForkServer(g, cl) if err != nil { return err } } else if libkb.IsBrewBuild { // If we're running in Brew mode, we might need to install ourselves as a persistent // service for future invocations of the command. newProc, err = install.AutoInstall(g, "", false) if err != nil { return err } } g.Log.Debug("| After forks; newProc=%v", newProc) if err = configureLogging(g, cl); err != nil { return err } // If we have created a new proc, then there's no need to keep going to the // final step, which is to check for a version clashes. if newProc { return nil } // Finally, we'll restart the service if we see that it's out of date. if err = client.FixVersionClash(g, cl); err != nil { return err } return nil }
// AutoFork? Standalone? ClientServer? Brew service? This function deals with the // various run configurations that we can run in. func configureProcesses(g *libkb.GlobalContext, cl *libcmdline.CommandLine, cmd *libcmdline.Command) (err error) { g.Log.Debug("+ configureProcesses") defer func() { g.Log.Debug("- configureProcesses -> %v", err) }() // On Linux, the service configures its own autostart file. Otherwise, no // need to configure if we're a service. if cl.IsService() { g.Log.Debug("| in configureProcesses, is service") if runtime.GOOS == "linux" { g.Log.Debug("| calling AutoInstall") _, err := install.AutoInstall(g, "", false, g.Log) if err != nil { return err } } return nil } // Start the server on the other end, possibly. // There are two cases in which we do this: (1) we want // a local loopback server in standalone mode; (2) we // need to "autofork" it. Do at most one of these // operations. if g.Env.GetStandalone() { if cl.IsNoStandalone() { err = fmt.Errorf("Can't run command in standalone mode") return err } err := service.NewService(g, false /* isDaemon */).StartLoopbackServer() if err != nil { if pflerr, ok := err.(libkb.PIDFileLockError); ok { err = fmt.Errorf("Can't run in standalone mode with a service running (see %q)", pflerr.Filename) return err } } return err } // After this point, we need to provide a remote logging story if necessary // If this command specifically asks not to be forked, then we are done in this // function. This sort of thing is true for the `ctl` commands and also the `version` // command. fc := cl.GetForkCmd() if fc == libcmdline.NoFork { return configureLogging(g, cl) } var newProc bool if libkb.IsBrewBuild { // If we're running in Brew mode, we might need to install ourselves as a persistent // service for future invocations of the command. newProc, err = install.AutoInstall(g, "", false, g.Log) if err != nil { return err } } else { // If this command warrants an autofork, do it now. if fc == libcmdline.ForceFork || g.Env.GetAutoFork() { newProc, err = client.AutoForkServer(g, cl) if err != nil { return err } } } // Restart the service if we see that it's out of date. It's important to do this // before we make any RPCs to the service --- for instance, before the logging // calls below. See the v1.0.8 update fiasco for more details. Also, only need // to do this if we didn't just start a new process. if !newProc { if err = client.FixVersionClash(g, cl); err != nil { return err } } g.Log.Debug("| After forks; newProc=%v", newProc) if err = configureLogging(g, cl); err != nil { return err } // This sends the client's PATH to the service so the service can update // its PATH if necessary. This is called after FixVersionClash(), which // happens above in configureProcesses(). if err = configurePath(g, cl); err != nil { // Further note -- don't die here. It could be we're calling this method // against an earlier version of the service that doesn't support it. // It's not critical that it succeed, so continue on. g.Log.Debug("Configure path failed: %v", err) } return nil }