简介
在 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开发还是比较快速的。