七叶笔记 » golang编程 » Golang – 实现linux 的scp功能

Golang – 实现linux 的scp功能

简介

linux 服务器上远程工具基本都是SSH,自动化实现的时候的,可以利用sshd直接进行部署,就不需要安装另外的agent。使用Python的时候,有 ansible 框架可以很快的实现。

使用Go也可以很快的实现一些SSH的功能。

拷贝文件就是一个比较常用的功能。

实现

这里使用官方的ssh结合sftp这个包来实现scp的功能。

 package ssh
​
import (
    "errors"
    "fmt"
    "io/ioutil"
    "net"
    "os"
    "time"
​
    " github .com/pkg/sftp"
    "golang.org/x/crypto/ssh"
)
​
// SftpClient sftp客户端
type SftpClient struct {
     Session  *sftp.Client
}
​
// NewSessionWithPassword 使用密码登录
func NewSessionWithPassword(host string, port int, user, password string) (sftpClient *SftpClient, err error) {
    sftpClient, err = NewSession(host, port, user, ssh.Password(password))
    return
}
​
// NewSessionWithKey 通过key登录sftp
func NewSessionWithKey(host string, port int, user, keyPath, keyPassword string) (sftpClient *SftpClient, err error) {
    fmt.Println(keyPath)
    keyData, err := ioutil.ReadFile(keyPath)
    if err != nil {
        return
    }
    fmt.Println(string(keyData))
    var singer ssh.Signer
    if keyPassword == "" {
        singer, err = ssh.ParsePrivateKey(keyData)
    } else {
        singer, err = ssh.ParsePrivateKeyWithPassphrase(keyData, [] byte (keyPassword))
    }
    if err != nil {
        return
    }
    sftpClient, err = NewSession(host, port, user, ssh.PublicKeys(singer))
    return
}
​
// NewSession 开启一个会话
func NewSession(host string, port int, user string, authMehtods ...ssh.AuthMethod) (sftpClient *SftpClient, err error) {
    clientConfig := &ssh.ClientConfig{
        User:    user,
        Auth:    authMehtods,
        Timeout: 4 * time.Second,
        HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
            return nil
        },
    }
    sshClient, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", host, port), clientConfig)
    if err != nil {
        return nil, err
    }
    sftpClient = &SftpClient{}
    sftpClient.Session, err = sftp.NewClient(sshClient)
    if err != nil {
        return nil, err
    }
    return
}
​
// ScopyRmoteFile 拷贝远程文件
func (sftpClient *SftpClient) ScopyRmoteFile(remoteFilePath, localFilePath string) (err error) {
    srcFile, err := sftpClient.Session.Open(remoteFilePath)
    if err != nil {
        return
    }
    defer srcFile. Close ()
    dstFile, err := os.Create(localFilePath)
    if err != nil {
        return
    }
    defer dstFile.Close()
    if _, err = srcFile.WriteTo(dstFile); err != nil {
        return
    }
    return
}
​
// SendFile 发送文件到远程
func (sftpClient *SftpClient) SendFile(localFilePath, remoteFilePath string) (err error) {
    srcFile, err := os.Open(localFilePath)
    if err != nil {
        return
    }
    defer srcFile.Close()
    dstFile, err := sftpClient.Session.Create(localFilePath)
    if err != nil {
        return
    }
    defer dstFile.Close()
    buf := make([]byte, 1024)
    for {
        n, _ := srcFile.Read(buf)
        if n == 0 {
            break
        }
        dstFile.Write(buf)
    }
    return
}
​
// Close close session
func (sftpClient *SftpClient) Close() (err error) {
    err = sftpClient.Session.Close()
    return
}
​  

使用

 package main
​
import (
   "mygolang/ssh"
)
​
func main(){
    sftpClient , err := NewSessionWithPassword("192.168.100.100",22,"root","opcai@2019")
    if err !=nil{
        panic(err)
    }
    defer sftpClient.Close()
    err = sftpClient.ScopyRemoteFile("/data/remotefile","/data/localfile")
    if err !=nil{
        panic(err)
    }
}  

总结

在做运维开发的时候,使用Golang开发还是比较快速的。

相关文章