站点更新:2018-11-14 16:13:16
This commit is contained in:
parent
3579e111a3
commit
3181b3f327
17
.vscode/launch.json
vendored
Normal file
17
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
// 使用 IntelliSense 了解相关属性。
|
||||
// 悬停以查看现有属性的描述。
|
||||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "auto",
|
||||
"program": "${fileDirname}",
|
||||
"env": {},
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
}
|
185
utils/ssh/main.go
Normal file
185
utils/ssh/main.go
Normal file
@ -0,0 +1,185 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
type SSHTerminal struct {
|
||||
Session *ssh.Session
|
||||
exitMsg string
|
||||
stdout io.Reader
|
||||
stdin io.Writer
|
||||
stderr io.Reader
|
||||
}
|
||||
|
||||
func main() {
|
||||
pwd := flag.String("pwd", "", "password")
|
||||
user := flag.String("user", "root", "user")
|
||||
ip := flag.String("ip", "", "ip")
|
||||
port := flag.Int("port", 22, "ssh port")
|
||||
flag.Parse()
|
||||
|
||||
if *ip == "" || *pwd == "" {
|
||||
fmt.Println("ip and passwod must be not null")
|
||||
os.Exit(3)
|
||||
}
|
||||
|
||||
sshConfig := &ssh.ClientConfig{
|
||||
User: *user,
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password(*pwd),
|
||||
},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", *ip, *port), sshConfig)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
err = New(client)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *SSHTerminal) updateTerminalSize() {
|
||||
go func() {
|
||||
// SIGWINCH is sent to the process when the window size of the terminal has
|
||||
// changed.
|
||||
sigwinchCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigwinchCh, syscall.SIGWINCH)
|
||||
|
||||
fd := int(os.Stdin.Fd())
|
||||
termWidth, termHeight, err := terminal.GetSize(fd)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
// The client updated the size of the local PTY. This change needs to occur
|
||||
// on the server side PTY as well.
|
||||
case sigwinch := <-sigwinchCh:
|
||||
if sigwinch == nil {
|
||||
return
|
||||
}
|
||||
currTermWidth, currTermHeight, err := terminal.GetSize(fd)
|
||||
|
||||
// Terminal size has not changed, don't do anything.
|
||||
if currTermHeight == termHeight && currTermWidth == termWidth {
|
||||
continue
|
||||
}
|
||||
|
||||
t.Session.WindowChange(currTermHeight, currTermWidth)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to send window-change reqest: %s.", err)
|
||||
continue
|
||||
}
|
||||
|
||||
termWidth, termHeight = currTermWidth, currTermHeight
|
||||
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
func (t *SSHTerminal) interactiveSession() error {
|
||||
defer func() {
|
||||
if t.exitMsg == "" {
|
||||
fmt.Fprintln(os.Stdout, "the connection was closed on the remote side on ", time.Now().Format(time.RFC822))
|
||||
} else {
|
||||
fmt.Fprintln(os.Stdout, t.exitMsg)
|
||||
}
|
||||
}()
|
||||
|
||||
fd := int(os.Stdin.Fd())
|
||||
state, err := terminal.MakeRaw(fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer terminal.Restore(fd, state)
|
||||
|
||||
termWidth, termHeight, err := terminal.GetSize(fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
termType := os.Getenv("TERM")
|
||||
if termType == "" {
|
||||
termType = "xterm-256color"
|
||||
}
|
||||
|
||||
err = t.Session.RequestPty(termType, termHeight, termWidth, ssh.TerminalModes{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.updateTerminalSize()
|
||||
|
||||
t.stdin, err = t.Session.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.stdout, err = t.Session.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.stderr, err = t.Session.StderrPipe()
|
||||
|
||||
go io.Copy(os.Stderr, t.stderr)
|
||||
go io.Copy(os.Stdout, t.stdout)
|
||||
go func() {
|
||||
buf := make([]byte, 128)
|
||||
for {
|
||||
n, err := os.Stdin.Read(buf)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
if n > 0 {
|
||||
_, err = t.stdin.Write(buf[:n])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.exitMsg = err.Error()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err = t.Session.Shell()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = t.Session.Wait()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func New(client *ssh.Client) error {
|
||||
session, err := client.NewSession()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
s := SSHTerminal{
|
||||
Session: session,
|
||||
}
|
||||
|
||||
return s.interactiveSession()
|
||||
}
|
Loading…
Reference in New Issue
Block a user