nsf / termbox-go

Pure Go termbox implementation
http://godoc.org/github.com/nsf/termbox-go
MIT License
4.66k stars 372 forks source link

panic: The handle is invalid. #217

Closed Mountains-and-rivers closed 3 years ago

Mountains-and-rivers commented 4 years ago

mycode:

package main
import (
    "fmt"
    "golang.org/x/crypto/ssh"
    "golang.org/x/crypto/ssh/terminal"
    "io"
    "net"
    "os"
    "time"
)

type Cli struct {
    IP         string      //IP地址
    Username   string      //用户名
    Password   string      //密码
    Port       int         //端口号
    client     *ssh.Client //ssh客户端
    LastResult string      //最近一次Run的结果
}

//创建命令行对象
//@param ip IP地址
//@param username 用户名
//@param password 密码
//@param port 端口号,默认22
func New(ip string, username string, password string, port ...int) *Cli {
    cli := new(Cli)
    cli.IP = ip
    cli.Username = username
    cli.Password = password
    if len(port) <= 0 {
        cli.Port = 22
    } else {
        cli.Port = port[0]
    }
    return cli
}

//执行shell
//@param shell shell脚本命令
func (c Cli) Run(shell string) (string, error) {
    if c.client == nil {
        if err := c.connect(); err != nil {
            return "", err
        }
    }
    session, err := c.client.NewSession()
    if err != nil {
        return "", err
    }
    defer session.Close()
    buf, err := session.CombinedOutput(shell)

    c.LastResult = string(buf)
    return c.LastResult, err
}
//连接
func (c *Cli) connect() error {
    config := ssh.ClientConfig{
        User: c.Username,
        Auth: []ssh.AuthMethod{ssh.Password(c.Password)},
        HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
            return nil
        },
        Timeout: 10 * time.Second,
    }
    addr := fmt.Sprintf("%s:%d", c.IP, c.Port)
    sshClient, err := ssh.Dial("tcp", addr, &config)
    if err != nil {
        return err
    }
    c.client = sshClient
    return nil
}
//执行带交互的命令
func (c *Cli) RunTerminal(shell string, stdout, stderr io.Writer) error {
    if c.client == nil {
        if err := c.connect(); err != nil {
            return err
        }
    }
    session, err := c.client.NewSession()
    if err != nil {
        return err
    }
    defer session.Close()

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

    session.Stdout = stdout
    session.Stderr = 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 {
        return err
    }

    session.Run(shell)
    return nil
}

func main(){
    cli := New("serverIP", "root", "passwd", 22)
    cli.RunTerminal("top", os.Stdout, os.Stdin)
}

run code env :

 x86 cpu and windows os 

go version:

go1.13.4 windows/amd64

run result:

panic: The handle is invalid.

goroutine 1 [running]:
main.(*Cli).RunTerminal(0xc000085f00, 0x5d131c, 0x3, 0x6057c0, 0xc000088008, 0x6057c0, 0xc000088000, 0x0, 0x0)
    D:/go/place/1.go:91 +0x4c1
main.main()
    D:/go/place/1.go:122 +0xff

can you help me? It's a question. Don't pretend that nothing happened. I find out that someone had asked the same question but you didn't answer him。

scrouthtv commented 3 years ago

I cannot reproduce this with go 1.15.4 windows/amd64 and the newest upstream version. I changed the values in your example with a second machine on my network, and when executing this, I get the very first line of output of top.

Does your issue persist or this is irrelevant meanwhile?