0
点赞
收藏
分享

微信扫一扫

#yyds干货盘点#golang详解ssh跟sftp

1.依赖包

import (    
"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"

下载依赖包使用

go get "github.com/pkg/sftp"
go get "golang.org/x/crypto/ssh"

或者

go mod download


2.创建client

type ClientConfig struct {
// Config contains configuration that is shared between clients and
// servers.
Config

// User contains the username to authenticate as.
User string

// Auth contains possible authentication methods to use with the
// server. Only the first instance of a particular RFC 4252 method will
// be used during authentication.
Auth []AuthMethod

// HostKeyCallback is called during the cryptographic
// handshake to validate the server's host key. The client
// configuration must supply this callback for the connection
// to succeed. The functions InsecureIgnoreHostKey or
// FixedHostKey can be used for simplistic host key checks.
HostKeyCallback HostKeyCallback

// BannerCallback is called during the SSH dance to display a custom
// server's message. The client configuration can supply this callback to
// handle it as wished. The function BannerDisplayStderr can be used for
// simplistic display on Stderr.
BannerCallback BannerCallback

// ClientVersion contains the version identification string that will
// be used for the connection. If empty, a reasonable default is used.
ClientVersion string

// HostKeyAlgorithms lists the key types that the client will
// accept from the server as host key, in order of
// preference. If empty, a reasonable default is used. Any
// string returned from PublicKey.Type method may be used, or
// any of the CertAlgoXxxx and KeyAlgoXxxx constants.
HostKeyAlgorithms []string

// Timeout is the maximum amount of time for the TCP connection to establish.
//
// A Timeout of zero means no timeout.
Timeout time.Duration
}
userName := request.Attribute(filters.UserName).(string)
PassWd := []ssh.AuthMethod{ssh.Password(config.Config.GetString("HARBOR_SSH_PASSWD"))}
Conf := ssh.ClientConfig{
User: "root",
Auth: PassWd,
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
}
Client, err := ssh.Dial("tcp", config.Config.GetString("HARBOR_SSH_ADDRESS"), &Conf)
if err != nil {
fmt.Println("创建Client失败", err)
panic(err)
}

#yyds干货盘点#golang详解ssh跟sftp_shell命令

3.用sshclient创建ftpClient

ftpClient, err := sftp.NewClient(Client)
if err != nil {
fmt.Println("创建ftp客户端失败", err)
panic(err)
}
defer ftpClient.Close()

4.使用方式

4.1判断文件或目录是否存在

//判断远端对应的文件或目录是否存在
func isExist(remoteDir string, ftpClient *sftp.Client) bool {
_, errs := ftpClient.Stat(remoteDir)
if errs != nil {
//文件不存在
return false
}
return true
}

4.2创建目录

//如果服务器对应的/home/user目录不存在就创建一个
func createDir(remoteDir string, ftpClient *sftp.Client) {
//获取路径的属性
_, errs := ftpClient.Stat(remoteDir)
if errs != nil {
//创建远程文件夹,如果不存在就创建一个
error := ftpClient.Mkdir(remoteDir)
if error != nil {
fmt.Println("创建远程ftp文件夹失败", error)
panic(error)
}
}
}

4.3ssh执行shell命令

func runCommand(commands string, client *ssh.Client) string {
var combo []byte
if session, err := client.NewSession(); err == nil {
defer session.Close()
//执行远程命令
combo, err = session.CombinedOutput(commands)
if err != nil {
log.Fatal("远程执行命令失败,", string(combo))
}
return string(combo)
}
return string(combo)
}

4.4文件上传

主要调用http.request的FormFile方法将文件解析成文件流

func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, error) {
if r.MultipartForm == multipartByReader {
return nil, nil, errors.New("http: multipart handled by MultipartReader")
}
if r.MultipartForm == nil {
err := r.ParseMultipartForm(defaultMaxMemory)
if err != nil {
return nil, nil, err
}
}
if r.MultipartForm != nil && r.MultipartForm.File != nil {
if fhs := r.MultipartForm.File[key]; len(fhs) > 0 {
f, err := fhs[0].Open()
return f, fhs[0], err
}
}
return nil, nil, ErrMissingFile
}
const FILE                  = "file" //前端字段值

upFile, fileHeader, err := request.Request.FormFile(FILE)
fileSuffix := path.Ext(fileHeader.Filename) //取文件后缀
filePrefix := fileHeader.Filename[0 : len(fileHeader.Filename)-len(fileSuffix)] //文件前缀

用ftpclient创建后端文件,然后把文件流write进去

dstFile, e := ftpClient.Create(path.Join(remoteDir, remoteFileName))
if e != nil {
fmt.Println("创建文件失败", e)
panic(e)
}
defer dstFile.Close()

buffer := make([]byte, 1024000)
for {
n, err := upFile.Read(buffer)
dstFile.Write(buffer[:n])
//注意,由于文件大小不定,不可直接使用buffer,否则会在文件末尾重复写入,以填充1024的整数倍
if err != nil {
if err == io.EOF {
fmt.Println("已读取到文件末尾")
break
} else {
fmt.Println("读取文件出错", err)
panic(err)
}
}
}

5.浅谈ftpclient跟shellClinet

ftp能进行的操作用shell执行shell命令几乎都能实现相应的功能,但是ftp的效率低,对应的安全性更高。文件相关操作使用

ftp更好,毕竟术业有专攻。其他的一些指令可以用shellClient的runCommand方法

举报

相关推荐

0 条评论