How to implement remote command execution using Go language

  • 2020-05-30 20:23:41
  • OfStack

preface

What is the use of remote command execution? Why execute commands remotely? If you only have 2 or 3 servers to manage, it really doesn't matter if you can execute commands remotely, you can log in to each server and do all kinds of things. When you have more than three servers, remote command execution can greatly increase your productivity.

If you have a tool that can execute commands remotely, you can operate multiple machines as if they were a single machine. The more machines you have, the more efficient you will be. The most common way to execute a command remotely is to use the SSH protocol to send the command to a remote machine for execution and get the result back.

1 a command

A "1" command is a command that will be executed within a certain time frame. grep, cat, etc. The steps to execute the command are: connect, execute, and get the result

The connection

The connection contains authentication, which can be done using either password or sshkey 2. The following example USES password authentication to complete the connection for simplicity.


import ( 
 "fmt"
 "time"

 "golang.org/x/crypto/ssh"
)

func connect(user, password, host string, port int) (*ssh.Session, error) { 
 var (
 auth  []ssh.AuthMethod
 addr  string
 clientConfig *ssh.ClientConfig
 client *ssh.Client
 session *ssh.Session
 err  error
 )
 // get auth method
 auth = make([]ssh.AuthMethod, 0)
 auth = append(auth, ssh.Password(password))

 clientConfig = &ssh.ClientConfig{
 User: user,
 Auth: auth,
 Timeout: 30 * time.Second,
 }

 // connet to ssh
 addr = fmt.Sprintf("%s:%d", host, port)

 if client, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
 return nil, err
 }

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

 return session, nil
}

The method of connection is simple, as long as the user *, * password *, * hostname or IP*, *SSH port is provided

Execute, command to get the result

Once the connection is successful, executing the command is simple


import ( 
 "fmt"
 "log"
 "os"
 "time"

 "golang.org/x/crypto/ssh"
)

func main() { 
 session, err := connect("root", "xxxxx", "127.0.0.1", 22)
 if err != nil {
 log.Fatal(err)
 }
 defer session.Close()

 session.Run("ls /; ls /abc")
}

After the above code runs, the command executes normally, but there is no normal output result, and there is no abnormal output result. To display the results, the Stdout and Stderr redirects of session need to modify func main as follows:


func main() { 
 session, err := connect("root", "xxxxx", "127.0.0.1", 22)
 if err != nil {
 log.Fatal(err)
 }
 defer session.Close()

 session.Stdout = os.Stdout
 session.Stderr = os.Stderr
 session.Run("ls /; ls /abc")
}

So you can display normal, abnormal information on the screen.

Interactive command

The above method cannot execute interactive commands remotely, such as top, or edit a file remotely, such as vi /etc/nginx/nginx.conf To support interactive commands, you need the current terminal to take over the remote PTY.


func main() { 
 session, err := connect("root", "olordjesus", "dockers.iotalabs.io", 2210)
 if err != nil {
 log.Fatal(err)
 }
 defer session.Close()

 fd := int(os.Stdin.Fd())
 oldState, err := terminal.MakeRaw(fd)
 if err != nil {
 panic(err)
 }
 defer terminal.Restore(fd, oldState)

 // excute command
 session.Stdout = os.Stdout
 session.Stderr = os.Stderr
 session.Stdin = os.Stdin

 termWidth, termHeight, err := terminal.GetSize(fd)
 if err != nil {
 panic(err)
 }

 // Set up terminal modes
 modes := ssh.TerminalModes{
 ssh.ECHO:  1, // enable 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-256color", termHeight, termWidth, modes); err != nil {
 log.Fatal(err)
 }

 session.Run("top")
}

conclusion

Ok, so you can perform interactive commands, such as the above top through vi etc/nginx/nignx conf commands to remote editing files. That's all about how to use Go to implement remote commands. I hope this article will help you learn python.


Related articles: