예제 #1
2
func tailFile(session *ssh.Session, file string, sudo bool, linec chan<- string) error {

	var command string
	if sudo {
		command = fmt.Sprintf("sudo /usr/bin/env tail -F %s", file)
	} else {
		command = fmt.Sprintf("/usr/bin/env tail -F %s", file)
	}

	var wg sync.WaitGroup
	errc := make(chan error, 3)
	consumeStream := func(r io.Reader) {
		defer wg.Done()
		scan := bufio.NewScanner(r)
		scan.Split(bufio.ScanLines)
		for scan.Scan() {
			linec <- scan.Text()
		}
		if err := scan.Err(); err != nil {
			errc <- err
		}
	}

	stderr, err := session.StderrPipe()
	if err != nil {
		return fmt.Errorf("opening stderr: %v", err)
	}
	stdout, err := session.StdoutPipe()
	if err != nil {
		return fmt.Errorf("opening stdout: %v", err)
	}

	wg.Add(1)
	go consumeStream(stderr)
	go consumeStream(stdout)

	if err := session.Start(command); err != nil {
		return err
	}
	wg.Add(1)
	go func() {
		if err := session.Wait(); err != nil {
			errc <- err
		}
	}()

	go func() {
		wg.Wait()
		close(errc)
	}()

	return <-errc
}
예제 #2
0
func (cmd *command) StartCommand() (error, *ssh.Session) {
	var (
		session *ssh.Session
		err     error
	)

	z := cmd.zh

	// open ssh link
	if z.client == nil {
		if err = z.dialSSH(); err != nil {
			return err, nil
		}
	}

	// establish ssh session
	if session, err = z.client.NewSession(); err != nil {
		return err, nil
	}

	// setup env, stdin, stdout, stderr
	if err = prepareCommand(session, cmd); err != nil {
		return err, nil
	}

	// start remote command
	err = session.Start(cmd.Path)
	if err == nil {
		return err, session
	}
	return err, nil
}
예제 #3
0
파일: ssh.go 프로젝트: treescale/treescale
func (ssc *SSHConfig) Exec(cmd string, stdout, stderr io.Writer, input chan string) (err tree_lib.TreeError) {
	var (
		session       *ssh.Session
		stdin         io.WriteCloser
		command_ended bool
	)
	err.From = tree_lib.FROM_SSH_EXEC
	session, err.Err = ssc.conn.NewSession()
	if !err.IsNull() {
		return
	}
	defer session.Close()

	session.Stdout = stdout
	session.Stderr = stderr

	stdin, err.Err = session.StdinPipe()
	if !err.IsNull() {
		return
	}

	err.Err = session.Start(cmd)
	if !err.IsNull() {
		return
	}
	command_ended = false
	go func() {
		for !command_ended {
			io.Copy(stdin, bytes.NewBufferString(<-input))
		}
	}()
	err.Err = session.Wait()
	command_ended = true
	return
}
예제 #4
0
// RunCommandBackground runs a background command in a vagrant node
func (n *VagrantNode) RunCommandBackground(cmd string) (string, error) {
	var (
		s   *ssh.Session
		err error
	)

	if s, err = n.client.NewSession(); err != nil {
		return "", err
	}
	defer s.Close()

	// start and forget about the command as user asked to run in background.
	// The limitation is we/ won't know if it fails though. Not a worry right
	// now as the test will fail anyways, but might be good to find a better way.
	return "", s.Start(newCmdStrWithSource(cmd))
}
예제 #5
0
func stream(command string, session *ssh.Session) (output chan string, done chan bool, err error) {
	outReader, err := session.StdoutPipe()
	Ω(err).ShouldNot(HaveOccurred())
	errReader, err := session.StderrPipe()
	Ω(err).ShouldNot(HaveOccurred())
	outputReader := io.MultiReader(outReader, errReader)
	err = session.Start(command)
	Ω(err).ShouldNot(HaveOccurred())
	scanner := bufio.NewScanner(outputReader)
	outputChan := make(chan string)
	done = make(chan bool)
	go func(scanner *bufio.Scanner, out chan string, done chan bool) {
		defer close(outputChan)
		defer close(done)
		for scanner.Scan() {
			outputChan <- scanner.Text()
		}
		done <- true
		session.Close()
	}(scanner, outputChan, done)
	return outputChan, done, err
}
				})
			})

			Context("while a command is running", func() {
				var stdin io.WriteCloser
				var stdout io.Reader

				BeforeEach(func() {
					var err error
					stdin, err = session.StdinPipe()
					Expect(err).NotTo(HaveOccurred())

					stdout, err = session.StdoutPipe()
					Expect(err).NotTo(HaveOccurred())

					err = session.Start("trap 'echo Caught SIGUSR1' USR1; echo trapped; cat")
					Expect(err).NotTo(HaveOccurred())

					reader := bufio.NewReader(stdout)
					Eventually(reader.ReadLine).Should(ContainSubstring("trapped"))
				})

				It("delivers the signal to the process", func() {
					err := session.Signal(ssh.SIGUSR1)
					Expect(err).NotTo(HaveOccurred())

					Eventually(runner.SignalCallCount).Should(Equal(1))

					err = stdin.Close()
					Expect(err).NotTo(HaveOccurred())
예제 #7
0
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
}
예제 #8
-1
func pipe(ch ssh.Channel, client *ssh.Client, session *ssh.Session, command string) (int, error) {
	targetStderr, err := session.StderrPipe()
	if err != nil {
		return -1, errors.New("fail to pipe stderr: " + err.Error())
	}
	targetStdout, err := session.StdoutPipe()
	if err != nil {
		return -1, errors.New("fail to pipe stdout: " + err.Error())
	}
	targetStdin, err := session.StdinPipe()
	if err != nil {
		return -1, errors.New("fail to pipe stdin: " + err.Error())
	}

	go io.Copy(targetStdin, ch)
	go io.Copy(ch.Stderr(), targetStderr)
	go io.Copy(ch, targetStdout)

	err = session.Start(command)
	if err != nil {
		ch.Write([]byte("Error when starting '" + command + "': " + err.Error()))
		ch.Close()
	}

	err = session.Wait()
	if err != nil {
		if err, ok := err.(*ssh.ExitError); ok {
			return err.ExitStatus(), nil
		} else {
			return -1, errors.New("failed to wait ssh command: " + err.Error())
		}
	}

	return 0, nil
}