server.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "os/exec"
  6. "strings"
  7. "time"
  8. )
  9. // Server ...
  10. type Server struct {
  11. Alias string
  12. Hostname string
  13. Notes string
  14. Tags []string
  15. Hit int
  16. port string
  17. RunCmd string
  18. }
  19. func (s Server) ssh() {
  20. if s.Notes != "" {
  21. renderNotes(s)
  22. }
  23. // TODO: this parsing should probably be done at time of server add.
  24. s.port = "22"
  25. if strings.Contains(s.Hostname, ":") {
  26. p := strings.Split(s.Hostname, ":")
  27. s.Hostname = p[0]
  28. s.port = p[1]
  29. }
  30. success := s.sshStartProcess()
  31. for success == false {
  32. handleWarning(fmt.Errorf("Reconnecting. Press Ctrl+C to abort."))
  33. time.Sleep(3000 * time.Millisecond)
  34. success = s.sshStartProcess()
  35. }
  36. }
  37. func (s Server) sshStartProcess() (success bool) {
  38. args := []string{"-p " + s.port, s.Hostname}
  39. if len(s.RunCmd) > 0 {
  40. // we have a command to run once we connect, so append it to the args we're sending ssh
  41. // specify -t to require a tty (just in case, for tmux/screen/etc)
  42. args = append(args, "-t", "--", s.RunCmd)
  43. }
  44. handleDebug(fmt.Sprintf("running ssh %s", args))
  45. cmd := exec.Command("ssh", args...)
  46. cmd.Stderr = os.Stderr
  47. cmd.Stdout = os.Stdout
  48. cmd.Stdin = os.Stdin
  49. err := cmd.Start()
  50. handleError(err)
  51. err = cmd.Wait()
  52. // 127 is command not found
  53. // 130 is ctrl+c
  54. // TODO: is there not a way to get the return code as an int?
  55. rs := cmd.ProcessState.String()
  56. if rs == "exit status 127" || rs == "exit status 130" {
  57. return true
  58. }
  59. return cmd.ProcessState.Success()
  60. }