-func (boot *bootCommand) installGoProgram(ctx context.Context, srcpath string) error {
- boot.goMutex.Lock()
- defer boot.goMutex.Unlock()
- return boot.RunProgram(ctx, filepath.Join(boot.sourcePath, srcpath), nil, []string{"GOPATH=" + boot.libPath}, "go", "install")
-}
-
-func (boot *bootCommand) setupRubyEnv() error {
- boot.setupRubyOnce.Do(func() {
- buf, err := exec.Command("gem", "env", "gempath").Output() // /var/lib/arvados/.gem/ruby/2.5.0/bin:...
- if err != nil || len(buf) == 0 {
- boot.setupRubyErr = fmt.Errorf("gem env gempath: %v", err)
- }
- gempath := string(bytes.Split(buf, []byte{':'})[0])
- os.Setenv("PATH", gempath+"/bin:"+os.Getenv("PATH"))
- os.Setenv("GEM_HOME", gempath)
- os.Setenv("GEM_PATH", gempath)
- })
- return boot.setupRubyErr
-}
-
-// Run prog with args, using dir as working directory. If ctx is
-// cancelled while the child is running, RunProgram terminates the
-// child, waits for it to exit, then returns.
-//
-// Child's environment will have our env vars, plus any given in env.
-//
-// Child's stdout will be written to output if non-nil, otherwise the
-// boot command's stderr.
-func (boot *bootCommand) RunProgram(ctx context.Context, dir string, output io.Writer, env []string, prog string, args ...string) error {
- cmdline := fmt.Sprintf("%s", append([]string{prog}, args...))
- fmt.Fprintf(boot.stderr, "%s executing in %s\n", cmdline, dir)
- cmd := exec.Command(prog, args...)
- if output == nil {
- cmd.Stdout = boot.stderr
- } else {
- cmd.Stdout = output
- }
- cmd.Stderr = boot.stderr
- if strings.HasPrefix(dir, "/") {
- cmd.Dir = dir
- } else {
- cmd.Dir = filepath.Join(boot.sourcePath, dir)
- }
- if env != nil {
- cmd.Env = append(env, os.Environ()...)
- }
- go func() {
- <-ctx.Done()
- log := ctxlog.FromContext(ctx).WithFields(logrus.Fields{"dir": dir, "cmdline": cmdline})
- for cmd.ProcessState == nil {
- // Child hasn't exited yet
- if cmd.Process == nil {
- log.Infof("waiting for child process to start")
- time.Sleep(time.Second)
- } else {
- log.WithField("PID", cmd.Process.Pid).Info("sending SIGTERM")
- cmd.Process.Signal(syscall.SIGTERM)
- log.WithField("PID", cmd.Process.Pid).Info("waiting for child process to exit after SIGTERM")
- time.Sleep(5 * time.Second)
- }
- }
- }()
- err := cmd.Run()
- if err != nil {
- return fmt.Errorf("%s: error: %v", cmdline, err)