golang通过SSH实现远程执行和SCP文件下载的插件库easyssh-proxy的使用

Golang通过SSH实现远程执行和SCP文件下载的插件库easyssh-proxy的使用

easyssh-proxy提供了Go语言中SSH协议功能的简单实现。

功能特性

这个项目是从easyssh分叉而来,但添加了以下功能:

  • 支持用户私钥的纯文本
  • 支持用户私钥的路径
  • 支持TCP连接建立的超时设置
  • 支持SSH ProxyCommand

使用示例

MakeConfig

所有功能都通过MakeConfig结构体的方法访问:

ssh := &easyssh.MakeConfig{
    User:    "drone-scp",
    Server:  "localhost",
    KeyPath: "./tests/.ssh/id_rsa",
    Port:    "22",
    Timeout: 60 * time.Second,
}

stdout, stderr, done, err := ssh.Run("ls -al", 60*time.Second)
err = ssh.Scp("/root/source.csv", "/tmp/target.csv")
stdoutChan, stderrChan, doneChan, errChan, err = ssh.Stream("for i in {1..5}; do echo ${i}; sleep 1; done; exit 2;", 60*time.Second)

SSH远程执行命令

package main

import (
  "fmt"
  "time"

  "github.com/appleboy/easyssh-proxy"
)

func main() {
  // 创建MakeConfig实例,包含远程用户名、服务器地址和私钥路径
  ssh := &easyssh.MakeConfig{
    User:   "appleboy",
    Server: "example.com",
    // 可选密钥或密码,如果两者都没有,我们会尝试联系您的代理SOCKET
    // Password: "password",
    // 粘贴您的私钥源内容
    // Key: `-----BEGIN RSA PRIVATE KEY-----
    // MIIEpAIBAAKCAQEA4e2D/qPN08pzTac+a8ZmlP1ziJOXk45CynMPtva0rtK/RB26
    // 7XC9wlRna4b3Ln8ew3q1ZcBjXwD4ppbTlmwAfQIaZTGJUgQbdsO9YA==
    // -----END RSA PRIVATE KEY-----
    // `,
    KeyPath: "/Users/username/.ssh/id_rsa",
    Port:    "22",
    Timeout: 60 * time.Second,

    // 使用密码短语解析私钥
    Passphrase: "1234",

    // 可选指纹SHA256验证
    // 获取指纹: ssh.FingerprintSHA256(key)
    // Fingerprint: "SHA256:mVPwvezndPv/ARoIadVY98vAC0g+P/5633yTC4d/wXE"

    // 启用不安全密码和密钥交换方法的使用
    // 这将启用以下不安全密码和密钥交换方法:
    // - aes128-cbc
    // - aes192-cbc
    // - aes256-cbc
    // - 3des-cbc
    // - diffie-hellman-group-exchange-sha256
    // - diffie-hellman-group-exchange-sha1
    // 这些算法不安全,可能允许攻击者恢复明文数据
    // UseInsecureCipher: true,
  }

  // 调用Run方法执行您想在远程服务器上运行的命令
  stdout, stderr, done, err := ssh.Run("ls -al", 60*time.Second)
  // 处理错误
  if err != nil {
    panic("Can't run remote command: " + err.Error())
  } else {
    fmt.Println("don is :", done, "stdout is :", stdout, ";   stderr is :", stderr)
  }
}

SCP文件传输

package main

import (
  "fmt"

  "github.com/appleboy/easyssh-proxy"
)

func main() {
  // 创建MakeConfig实例,包含远程用户名、服务器地址和私钥路径
  ssh := &easyssh.MakeConfig{
    User:     "appleboy",
    Server:   "example.com",
    Password: "123qwe",
    Port:     "22",
  }

  // 调用Scp方法上传文件到远程服务器
  // 请确保`tmp`文件夹存在
  err := ssh.Scp("/root/source.csv", "/tmp/target.csv")

  // 处理错误
  if err != nil {
    panic("Can't run remote command: " + err.Error())
  } else {
    fmt.Println("success")
  }
}

SSH ProxyCommand

ssh := &easyssh.MakeConfig{
    User:    "drone-scp",
    Server:  "localhost",
    Port:    "22",
    KeyPath: "./tests/.ssh/id_rsa",
    Timeout: 60 * time.Second,
    Proxy: easyssh.DefaultConfig{
      User:    "drone-scp",
      Server:  "localhost",
      Port:    "22",
      KeyPath: "./tests/.ssh/id_rsa",
      Timeout: 60 * time.Second,
    },
}

注意:Proxy连接的属性不会从跳板机继承。您必须在DefaultConfig结构体中明确指定它们。

SSH Stream日志

func main() {
  // 创建MakeConfig实例,包含远程用户名、服务器地址和私钥路径
  ssh := &easyssh.MakeConfig{
    Server:  "localhost",
    User:    "drone-scp",
    KeyPath: "./tests/.ssh/id_rsa",
    Port:    "22",
    Timeout: 60 * time.Second,
  }

  // 调用Run方法执行您想在远程服务器上运行的命令
  stdoutChan, stderrChan, doneChan, errChan, err := ssh.Stream("for i in {1..5}; do echo ${i}; sleep 1; done; exit 2;", 60*time.Second)
  // 处理错误
  if err != nil {
    panic("Can't run remote command: " + err.Error())
  } else {
    // 从输出通道读取,直到收到完成信号
    isTimeout := true
  loop:
    for {
      select {
      case isTimeout = <-doneChan:
        break loop
      case outline := <-stdoutChan:
        fmt.Println("out:", outline)
      case errline := <-stderrChan:
        fmt.Println("err:", errline)
      case err = <-errChan:
      }
    }

    // 获取退出代码或命令错误
    if err != nil {
      fmt.Println("err: " + err.Error())
    }

    // 命令超时
    if !isTimeout {
      fmt.Println("Error: command timeout")
    }
  }
}

更多关于golang通过SSH实现远程执行和SCP文件下载的插件库easyssh-proxy的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang通过SSH实现远程执行和SCP文件下载的插件库easyssh-proxy的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用easyssh-proxy实现Golang远程SSH执行和SCP文件下载

easyssh-proxy是一个简单易用的Golang SSH库,它提供了远程命令执行和SCP文件传输功能。下面我将详细介绍如何使用这个库。

安装

首先安装easyssh-proxy库:

go get github.com/appleboy/easyssh-proxy

基本用法

1. 远程命令执行

package main

import (
	"fmt"
	"log"

	"github.com/appleboy/easyssh-proxy"
)

func main() {
	// 创建SSH配置
	ssh := &easyssh.MakeConfig{
		User:     "username",
		Server:   "example.com",
		Port:     "22",
		Password: "password",
		// 或者使用私钥认证
		// Key:     "/.ssh/id_rsa",
		// KeyPath: "/.ssh/id_rsa",
		Timeout: 30, // 超时时间(秒)
	}

	// 执行远程命令
	stdout, stderr, done, err := ssh.Run("ls -l /", 30)
	if err != nil {
		log.Fatalf("命令执行失败: %v", err)
	}

	fmt.Println("执行状态:", done)
	fmt.Println("标准输出:", stdout)
	fmt.Println("标准错误:", stderr)
}

2. SCP文件下载

package main

import (
	"fmt"
	"log"

	"github.com/appleboy/easyssh-proxy"
)

func main() {
	ssh := &easyssh.MakeConfig{
		User:     "username",
		Server:   "example.com",
		Port:     "22",
		Password: "password",
		Timeout:  30,
	}

	// 从远程服务器下载文件
	err := ssh.Scp("/remote/path/file.txt", "/local/path/file.txt")
	if err != nil {
		log.Fatalf("文件下载失败: %v", err)
	}

	fmt.Println("文件下载成功")
}

3. SCP文件上传

package main

import (
	"fmt"
	"log"

	"github.com/appleboy/easyssh-proxy"
)

func main() {
	ssh := &easyssh.MakeConfig{
		User:     "username",
		Server:   "example.com",
		Port:     "22",
		Password: "password",
		Timeout:  30,
	}

	// 上传文件到远程服务器
	err := ssh.Scp("/local/path/file.txt", "/remote/path/file.txt")
	if err != nil {
		log.Fatalf("文件上传失败: %v", err)
	}

	fmt.Println("文件上传成功")
}

高级功能

1. 使用代理

ssh := &easyssh.MakeConfig{
	User:    "username",
	Server:  "target.example.com",
	Port:    "22",
	KeyPath: "/.ssh/id_rsa",
	Proxy: easyssh.DefaultConfig{
		User:    "proxyuser",
		Server:  "proxy.example.com",
		Port:    "22",
		KeyPath: "/.ssh/proxy_id_rsa",
	},
}

2. 超时设置

ssh := &easyssh.MakeConfig{
	User:     "username",
	Server:   "example.com",
	Password: "password",
	Timeout:  60, // 60秒超时
}

3. 并行执行多个命令

package main

import (
	"fmt"
	"log"
	"sync"

	"github.com/appleboy/easyssh-proxy"
)

func main() {
	ssh := &easyssh.MakeConfig{
		User:     "username",
		Server:   "example.com",
		Password: "password",
	}

	var wg sync.WaitGroup
	commands := []string{"uname -a", "df -h", "free -m"}

	for _, cmd := range commands {
		wg.Add(1)
		go func(command string) {
			defer wg.Done()
			stdout, stderr, done, err := ssh.Run(command, 30)
			if err != nil {
				log.Printf("命令 %s 执行失败: %v", command, err)
				return
			}
			fmt.Printf("命令: %s\n状态: %t\n输出: %s\n错误: %s\n\n", 
				command, done, stdout, stderr)
		}(cmd)
	}

	wg.Wait()
}

错误处理

package main

import (
	"fmt"
	"log"

	"github.com/appleboy/easyssh-proxy"
)

func main() {
	ssh := &easyssh.MakeConfig{
		User:     "wronguser", // 错误的用户名
		Server:   "example.com",
		Password: "wrongpass", // 错误的密码
		Timeout:  10,
	}

	_, _, _, err := ssh.Run("ls", 10)
	if err != nil {
		switch e := err.(type) {
		case *easyssh.SshError:
			fmt.Printf("SSH错误: %s\n", e.Message)
			fmt.Printf("退出状态: %d\n", e.ExitStatus)
		default:
			log.Fatalf("未知错误: %v", err)
		}
		return
	}
}

总结

easyssh-proxy提供了简单易用的API来实现Golang中的SSH远程命令执行和SCP文件传输功能。它的主要特点包括:

  1. 支持密码和密钥认证
  2. 支持SSH代理
  3. 提供超时控制
  4. 简单的错误处理机制
  5. 支持并行执行

对于更复杂的SSH操作,可以考虑使用golang.org/x/crypto/ssh标准库,但对于大多数常见任务,easyssh-proxy提供了更简洁的接口。

回到顶部