Golang的SSH - 如何在同一个会话上运行多个命令? [英] Golang ssh - how to run multiple commands on the same session?

查看:1399
本文介绍了Golang的SSH - 如何在同一个会话上运行多个命令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过 ssh 运行多个命令,但似乎是 Session.Run 每个会话只允许一个命令(除非我错了) 。我想知道如何绕过这个限制,重新使用会话或发送一系列命令。
原因是我需要在同一个会话中使用下一个命令(sh /usr/bin/myscript.sh)运行 sudo su

解决方案

针对您的特定问题,您可以轻松运行 sudo /path/to/script.sh,这让我震惊,没有一种简单的方法在同一个会话中运行多个命令,所以我想出了一个 var wg(chan字符串,1) sync.WaitGroup
wg.Add(1)//对于shell本身
去func(){
for cmd:=范围在{
wg.Add(1)
w.Write([] byte(cmd +\\\
))
wg.Wait()
}
}()
go func(){
var(
buf [65 * 1024] byte
t

为{
n,err:= r.Read(buf [t:])
if err!= nil {
close(in)
close(out)
return
}
t + = n
if buf [t-2] =='$'{//假设$ PS1 ==' sh-4.3 $'
out< - string(buf [:t])
t = 0
wg.Done()
}
}
}()
return in,out
}

func main(){
config:=& ssh.ClientConfig {
User:kf5 ,
认证:[] ssh.AuthMethod {
ssh.Password(kf5),
},
}
client,err:= ssh.Dial (tcp,127.0.0.1:22,config)
if err!= nil {
panic(err)
}

defer client.Close ()
session,err:= client.NewSession()

if err!= nil {
log.Fatalf(无法创建s ession:%s,err)
}
推迟session.Close()

模式:= ssh.TerminalModes {
ssh.ECHO:0,//禁用回显
ssh.TTY_OP_ISPEED:14400,//输入速度= 14.4kbaud
ssh.TTY_OP_OSPEED:14400,//输出速度= 14.4kbaud
}

if err:= session.RequestPty(xterm,80,40,modes); err!= nil {
log.Fatal(err)
}
$ bw,err:= session.StdinPipe()
if err!= nil {
恐慌(错误)
}
r,错误:= session.StdoutPipe()
if err!= nil {
panic(err)
}
in,out:= MuxShell(w,r)
if err:= session.Start(/ bin / sh); err!= nil {
log.Fatal(err)
}
< -out //忽略shell输出
in< - ls -lhav
fmt.Printf(ls输出:%s \\\
,< -out)

in< - whoami
fmt.Printf(whoami:%s \\ \\ n,< -out)

in< - exit
session.Wait()
}

如果您的shell提示符不以 $ ($紧跟一个空格)结尾,死锁,因此它为什么是黑客。


I'm trying to run multiple commands through ssh but seems that Session.Run allows only one command per session ( unless I'm wrong). I'm wondering how can I bypass this limitation and reuse the session or send a sequence of commands. The reason is that I need to run sudo su within the same session with the next command ( sh /usr/bin/myscript.sh )

解决方案

While for your specific problem, you can easily run sudo /path/to/script.sh, it shock me that there wasn't a simple way to run multiple commands on the same session, so I came up with a bit of a hack, YMMV:

func MuxShell(w io.Writer, r io.Reader) (chan<- string, <-chan string) {
    in := make(chan string, 1)
    out := make(chan string, 1)
    var wg sync.WaitGroup
    wg.Add(1) //for the shell itself
    go func() {
        for cmd := range in {
            wg.Add(1)
            w.Write([]byte(cmd + "\n"))
            wg.Wait()
        }
    }()
    go func() {
        var (
            buf [65 * 1024]byte
            t   int
        )
        for {
            n, err := r.Read(buf[t:])
            if err != nil {
                close(in)
                close(out)
                return
            }
            t += n
            if buf[t-2] == '$' { //assuming the $PS1 == 'sh-4.3$ '
                out <- string(buf[:t])
                t = 0
                wg.Done()
            }
        }
    }()
    return in, out
}

func main() {
    config := &ssh.ClientConfig{
        User: "kf5",
        Auth: []ssh.AuthMethod{
            ssh.Password("kf5"),
        },
    }
    client, err := ssh.Dial("tcp", "127.0.0.1:22", config)
    if err != nil {
        panic(err)
    }

    defer client.Close()
    session, err := client.NewSession()

    if err != nil {
        log.Fatalf("unable to create session: %s", err)
    }
    defer session.Close()

    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
    }

    if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
        log.Fatal(err)
    }

    w, err := session.StdinPipe()
    if err != nil {
        panic(err)
    }
    r, err := session.StdoutPipe()
    if err != nil {
        panic(err)
    }
    in, out := MuxShell(w, r)
    if err := session.Start("/bin/sh"); err != nil {
        log.Fatal(err)
    }
    <-out //ignore the shell output
    in <- "ls -lhav"
    fmt.Printf("ls output: %s\n", <-out)

    in <- "whoami"
    fmt.Printf("whoami: %s\n", <-out)

    in <- "exit"
    session.Wait()
}

If your shell prompt doesn't end with $ ($ followed by a space), this will deadlock, hence why it's a hack.

这篇关于Golang的SSH - 如何在同一个会话上运行多个命令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆