fix: stream output from remote ssh commands
This commit is contained in:
parent
aec11bda28
commit
066b2b9373
|
@ -225,14 +225,12 @@ func installDocker(c *cli.Context, cl *dockerClient.Client, sshCl *simplessh.Cli
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
logrus.Debugf("running '%s' on %s now with sudo password", cmd, domainName)
|
logrus.Debugf("running '%s' on %s now with sudo password", cmd, domainName)
|
||||||
_, err := sshCl.ExecSudo(cmd, sudoPass)
|
if err := ssh.RunSudoCmd(cmd, sudoPass, sshCl); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logrus.Debugf("running '%s' on %s now without sudo password", cmd, domainName)
|
logrus.Debugf("running '%s' on %s now without sudo password", cmd, domainName)
|
||||||
_, err := sshCl.Exec(cmd)
|
if err := ssh.Exec(cmd, sshCl); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
130
pkg/ssh/ssh.go
130
pkg/ssh/ssh.go
|
@ -1,7 +1,12 @@
|
||||||
package ssh
|
package ssh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
"os/user"
|
"os/user"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
|
@ -94,3 +99,128 @@ func New(domainName, sshAuth, username, port string) (*simplessh.Client, error)
|
||||||
|
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sudoWriter supports sudo command handling.
|
||||||
|
// https://github.com/sfreiberg/simplessh/blob/master/simplessh.go
|
||||||
|
type sudoWriter struct {
|
||||||
|
b bytes.Buffer
|
||||||
|
pw string
|
||||||
|
stdin io.Writer
|
||||||
|
m sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write satisfies the write interface for sudoWriter.
|
||||||
|
// https://github.com/sfreiberg/simplessh/blob/master/simplessh.go
|
||||||
|
func (w *sudoWriter) Write(p []byte) (int, error) {
|
||||||
|
if string(p) == "sudo_password" {
|
||||||
|
w.stdin.Write([]byte(w.pw + "\n"))
|
||||||
|
w.pw = ""
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
w.m.Lock()
|
||||||
|
defer w.m.Unlock()
|
||||||
|
|
||||||
|
return w.b.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunSudoCmd runs SSH commands and streams output.
|
||||||
|
// https://github.com/sfreiberg/simplessh/blob/master/simplessh.go
|
||||||
|
func RunSudoCmd(cmd, passwd string, cl *simplessh.Client) error {
|
||||||
|
session, err := cl.SSHClient.NewSession()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
cmd = "sudo -p " + "sudo_password" + " -S " + cmd
|
||||||
|
|
||||||
|
w := &sudoWriter{
|
||||||
|
pw: passwd,
|
||||||
|
}
|
||||||
|
w.stdin, err = session.StdinPipe()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
session.Stdout = w
|
||||||
|
session.Stderr = w
|
||||||
|
|
||||||
|
done := make(chan struct{})
|
||||||
|
scanner := bufio.NewScanner(session.Stdin)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
fmt.Println(line)
|
||||||
|
}
|
||||||
|
done <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := session.Start(cmd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
<-done
|
||||||
|
|
||||||
|
if err := session.Wait(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exec runs a command on a remote and streams output.
|
||||||
|
// https://github.com/sfreiberg/simplessh/blob/master/simplessh.go
|
||||||
|
func Exec(cmd string, cl *simplessh.Client) error {
|
||||||
|
session, err := cl.SSHClient.NewSession()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
stdout, err := session.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
stderr, err := session.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
stdoutDone := make(chan struct{})
|
||||||
|
stdoutScanner := bufio.NewScanner(stdout)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for stdoutScanner.Scan() {
|
||||||
|
line := stdoutScanner.Text()
|
||||||
|
fmt.Println(line)
|
||||||
|
}
|
||||||
|
stdoutDone <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
|
stderrDone := make(chan struct{})
|
||||||
|
stderrScanner := bufio.NewScanner(stderr)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for stderrScanner.Scan() {
|
||||||
|
line := stderrScanner.Text()
|
||||||
|
fmt.Println(line)
|
||||||
|
}
|
||||||
|
stderrDone <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := session.Start(cmd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
<-stdoutDone
|
||||||
|
<-stderrDone
|
||||||
|
|
||||||
|
if err := session.Wait(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue