Context("when the command exits with a non-zero value", func() { It("it preserve the exit code", func() { err := session.Run("exit 3") Expect(err).To(HaveOccurred()) exitErr, ok := err.(*ssh.ExitError) Expect(ok).To(BeTrue()) Expect(exitErr.ExitStatus()).To(Equal(3)) }) }) Context("when a signal is sent across the session", func() { Context("before a command has been run", func() { BeforeEach(func() { err := session.Signal(ssh.SIGTERM) Expect(err).NotTo(HaveOccurred()) }) It("does not prevent the command from running", func() { result, err := session.Output("/bin/echo -n 'still kicking'") Expect(err).NotTo(HaveOccurred()) Expect(string(result)).To(Equal("still kicking")) }) }) Context("while a command is running", func() { var stdin io.WriteCloser var stdout io.Reader BeforeEach(func() {
func (s *BotClientT) Start(botId string, botInstance int, cmdline string, cfg *ConfigT, debugLevel int) error { var err error var sshclient *ssh.Client var session *ssh.Session // var wg sync.WaitGroup var cmd string if s.Host[botInstance].Status == BotStatPaused { return nil } if s.Host[botInstance].Status == BotStatRunning { err = s.PingAt(botId, botInstance, cfg) if err == nil { Goose.Ping.Logf(2, "bot %s@%s is alive", botId, s.Host[botInstance].Name) return nil } } Goose.StartStop.Logf(2, "Starting bot %s@%s", botId, s.Host[botInstance].Name) s.Host[botInstance].Status = BotStatUnreachable if s.Host[botInstance].OnStatUpdate != nil { s.Host[botInstance].OnStatUpdate(BotStatUnreachable) } cfg.SshClientConfig.User = s.SysUser sshclient, err = ssh.Dial("tcp", s.Host[botInstance].Name+":22", cfg.SshClientConfig) if err != nil { Goose.StartStop.Logf(1, "%s (%s)", ErrDialingToBot, err) return ErrDialingToBot } defer sshclient.Close() Goose.StartStop.Logf(3, "Dialed to bot %s@%s", botId, s.Host[botInstance].Name) session, err = sshclient.NewSession() if err != nil { Goose.StartStop.Logf(1, "%s (%s)", ErrCreatingSession, err) return ErrCreatingSession } defer session.Close() Goose.StartStop.Logf(3, "Session started at bot %s@%s", botId, s.Host[botInstance].Name) /* wg.Add(1) go func() { defer wg.Done() w, _ := session.StdinPipe() defer w.Close() Goose.StartStop.Logf(2,"Closing stdin for bot %s",botId) //fmt.Fprintf(w, "%s\n", config) }() */ /* // Set up terminal modes modes := ssh.TerminalModes{ ssh.ECHO: 0, // disable echoing ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud } // Request pseudo terminal if err := session.RequestPty("xterm", 80, 40, modes); err != nil { Goose.StartStop.Fatalf(1,"request for pseudo terminal failed: %s", err) } session.Stdout = &bytes.Buffer{} session.Stderr = &bytes.Buffer{} */ cmd = fmt.Sprintf("%s%c%s -v %d %s", s.BinDir, os.PathSeparator, s.BinName, debugLevel, cmdline) Goose.StartStop.Logf(3, "Will run %s@%s using %s", botId, s.Host[botInstance].Name, cmd) err = session.Start(cmd) // err = session.Run(cmd) Goose.StartStop.Logf(2, "Running bot %s", botId) // wg.Wait() if err != nil { session.Signal(ssh.SIGKILL) Goose.StartStop.Logf(1, "%s (%s)", ErrFailedStartingBot, err) return ErrFailedStartingBot } Goose.StartStop.Logf(2, "Started bot %s with cmd:[%s]", botId, cmd) s.Host[botInstance].Status = BotStatRunning if s.Host[botInstance].OnStatUpdate != nil { s.Host[botInstance].OnStatUpdate(BotStatRunning) } return nil }