2018-11-06 15:37:35 +08:00
|
|
|
|
package ssh
|
|
|
|
|
|
|
|
|
|
import (
|
2018-12-19 14:33:31 +08:00
|
|
|
|
"bufio"
|
|
|
|
|
"bytes"
|
|
|
|
|
"errors"
|
2018-11-06 15:37:35 +08:00
|
|
|
|
"fmt"
|
2018-12-19 14:33:31 +08:00
|
|
|
|
"io"
|
2018-11-06 15:37:35 +08:00
|
|
|
|
"path/filepath"
|
|
|
|
|
)
|
|
|
|
|
|
2018-12-19 14:33:31 +08:00
|
|
|
|
// Run Execute cmd on the remote host for daemon service
|
|
|
|
|
func (c *Client) Run(cmd string) {
|
2018-11-06 15:37:35 +08:00
|
|
|
|
session, err := c.SSHClient.NewSession()
|
|
|
|
|
if err != nil {
|
2018-12-19 14:33:31 +08:00
|
|
|
|
return
|
2018-11-06 15:37:35 +08:00
|
|
|
|
}
|
|
|
|
|
defer session.Close()
|
|
|
|
|
|
2018-12-19 14:33:31 +08:00
|
|
|
|
session.Start(cmd)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Printf("exec command:%v error:%v\n", cmd, err)
|
|
|
|
|
}
|
|
|
|
|
fmt.Printf("Waiting for command:%v to finish...\n", cmd)
|
|
|
|
|
//阻塞等待fork出的子进程执行的结果,和cmd.Start()配合使用[不等待回收资源,会导致fork出执行shell命令的子进程变为僵尸进程]
|
|
|
|
|
err = session.Wait()
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Printf(":Command finished with error: %v\n", err)
|
|
|
|
|
}
|
|
|
|
|
return
|
2018-11-06 15:37:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-19 14:33:31 +08:00
|
|
|
|
//Exec Execute cmd on the remote host and bind stderr and stdout
|
|
|
|
|
func (c *Client) Exec(cmd string) error {
|
2018-11-06 15:37:35 +08:00
|
|
|
|
session, err := c.SSHClient.NewSession()
|
|
|
|
|
if err != nil {
|
2018-12-19 14:33:31 +08:00
|
|
|
|
return err
|
2018-11-06 15:37:35 +08:00
|
|
|
|
}
|
|
|
|
|
defer session.Close()
|
2018-12-19 14:33:31 +08:00
|
|
|
|
// session.Run(cmd)
|
|
|
|
|
// return session.CombinedOutput(cmd)
|
|
|
|
|
stdout, err := session.StdoutPipe()
|
|
|
|
|
// stderr, err = session.StderrPipe()
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
2018-11-06 15:37:35 +08:00
|
|
|
|
|
2018-12-19 14:33:31 +08:00
|
|
|
|
var b bytes.Buffer
|
|
|
|
|
session.Stderr = &b
|
|
|
|
|
session.Start(cmd)
|
|
|
|
|
//创建一个流来读取管道内内容,这里逻辑是通过一行一行的读取的
|
|
|
|
|
reader := bufio.NewReader(stdout)
|
|
|
|
|
|
|
|
|
|
//实时循环读取输出流中的一行内容
|
|
|
|
|
for {
|
|
|
|
|
line, err2 := reader.ReadString('\n')
|
|
|
|
|
if err2 != nil || io.EOF == err2 {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
print(line)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//阻塞直到该命令执行完成,该命令必须是被Start方法开始执行的
|
|
|
|
|
session.Wait()
|
|
|
|
|
if b.Len() > 0 {
|
|
|
|
|
return errors.New(b.String())
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Output Execute cmd on the remote host and return stderr and stdout
|
|
|
|
|
func (c *Client) Output(cmd string) ([]byte, error) {
|
|
|
|
|
session, err := c.SSHClient.NewSession()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
defer session.Close()
|
|
|
|
|
// session.Run(cmd)
|
|
|
|
|
// return session.CombinedOutput(cmd)
|
|
|
|
|
return session.Output(cmd)
|
2018-11-06 15:37:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RunScript Executes a shell script file on the remote machine.
|
|
|
|
|
// It is copied in the tmp folder and ran in a single session.
|
|
|
|
|
// chmod +x is applied before running.
|
|
|
|
|
// Returns an SshResponse and an error if any has occured
|
|
|
|
|
func (c *Client) RunScript(scriptPath string) ([]byte, error) {
|
|
|
|
|
session, err := c.SSHClient.NewSession()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
defer session.Close()
|
|
|
|
|
|
|
|
|
|
// 1. 上传 script
|
2018-11-13 17:42:29 +08:00
|
|
|
|
remotePath := fmt.Sprintf("/tmp/script/%s", filepath.Base(scriptPath))
|
2018-11-06 15:37:35 +08:00
|
|
|
|
if err := c.UploadFile(scriptPath, remotePath); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
// 2. 执行script
|
|
|
|
|
rCmd := fmt.Sprintf("chmod +x %s ; %s", remotePath, remotePath)
|
|
|
|
|
return session.CombinedOutput(rCmd)
|
|
|
|
|
}
|