本人通过ssh公钥、私钥先实现可以通过ssh登录到目标机器
ssh [email protected]
注意这里是免密登录
然后通过指定公钥的方式,实现golang sftp协议传输文件
package main
//go run ops-sftp.go hosts 10.1.1.1,10.1.1.2 /workspace/test/w.txt /workspace/test/source.txt
import (
"fmt"
"ops-client/utils/sshClient"
"os"
"strings"
"sync"
"time"
)
func main() {
actionType:=os.Args[1]
ips:=os.Args[2]
ip_array:=strings.Split(ips,",")
writeFile:=os.Args[3]
sourceFile:=os.Args[4]
host, _ := os.Hostname()
privateKeyFile := ""
if host == "MacOS.local" {
privateKeyFile = "/Users/my/.ssh/id_rsa"
} else {
privateKeyFile = "/home/www/.ssh/id_rsa"
}
var wg sync.WaitGroup
tmpSourceFile:=sourceFile
for _, ip := range ip_array {
wg.Add(1)
if actionType=="hosts" {
tmpSourceFile=sourceFile+"."+ip
}
//ip="10.211.163.81"
go func(ip, privateKeyFile,writeFile,tmpSourceFile string) {
defer wg.Add(-1)
err := sshClient.Sftp(ip, privateKeyFile,writeFile,tmpSourceFile)
if err!=nil {
time.Sleep(2 * time.Second)
err := sshClient.Sftp(ip, privateKeyFile,writeFile,tmpSourceFile)
if err!=nil {
fmt.Println(ip,"\t",err)
os.Exit(1)
}
}
}(ip, privateKeyFile,writeFile,tmpSourceFile)
time.Sleep(10 * time.Millisecond)
}
wg.Wait()
}
自定义 sshClient 包,新建文件 common.go
package sshClient
import (
"bytes"
"golang.org/x/crypto/ssh"
"io"
"io/ioutil"
"log"
"os"
"time"
"github.com/pkg/sftp"
)
func CollectTest(ip string,privateKeyFile string) bool {
remoteIP := ip+":22"
user := "root"
privateKeyBytes, err := ioutil.ReadFile(privateKeyFile)
if err != nil {
log.Fatal(err)
}
//privateKeyBytes:=[]byte(privateKeyString)
key, err := ssh.ParsePrivateKey(privateKeyBytes)
if err != nil {
log.Fatal(err)
}
config := &ssh.ClientConfig{
User: user,
Auth: []ssh.AuthMethod{
// Use the PublicKeys method for remote authentication.
ssh.PublicKeys(key),
},
// using InsecureIgnoreHostKey() for testing purposes
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Timeout:1 * time.Second,
}
client, err := ssh.Dial("tcp", remoteIP, config)
if err != nil {
//log.Fatalf("unable to connect: %v", err)
return false
}
defer client.Close()
return true
}
func RunCommand(ip string,privateKeyFile string,cmdString string) (string,string,error) {
remoteIP := ip+":22"
user := "root"
privateKeyBytes, err := ioutil.ReadFile(privateKeyFile)
if err != nil {
log.Fatal(err)
}
key, err := ssh.ParsePrivateKey(privateKeyBytes)
if err != nil {
log.Fatal(err)
}
config := &ssh.ClientConfig{
User: user,
Auth: []ssh.AuthMethod{
ssh.PublicKeys(key),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Timeout:1 * time.Second,
}
client, err := ssh.Dial("tcp", remoteIP, config)
if err != nil {
//log.Fatalf("unable to connect: %v", err)
return "","",err
}
defer client.Close()
var stdOut, stdErr bytes.Buffer
// create session
session, err := client.NewSession();
defer session.Close()
if err != nil {
return "","",err
}
session.Stdout = &stdOut
session.Stderr = &stdErr
err=session.Run(cmdString)
return stdOut.String(),stdErr.String(),err
}
func Sftp(ip,privateKeyFile,writeFile,sourceFile string) (error) {
remoteIP := ip+":22"
user := "root"
privateKeyBytes, err := ioutil.ReadFile(privateKeyFile)
if err != nil {
log.Fatal(err)
}
key, err := ssh.ParsePrivateKey(privateKeyBytes)
if err != nil {
log.Fatal(err)
}
config := &ssh.ClientConfig{
User: user,
Auth: []ssh.AuthMethod{
ssh.PublicKeys(key),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Timeout:1 * time.Second,
}
client, err := ssh.Dial("tcp", remoteIP, config)
if err != nil {
return err
}
defer client.Close()
c, err := sftp.NewClient(client)
if err != nil {
log.Fatalf("unable to start sftp subsytem: %v", err)
}
defer c.Close()
w, err := c.OpenFile(writeFile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE)
if err != nil {
return err
}
defer w.Close()
f, err := os.Open(sourceFile)
if err != nil {
return err
}
defer f.Close()
t1 := time.Now()
n, err := io.Copy(w, f)
if err != nil {
return err
}
log.Printf("wrote %v bytes in %s", n, time.Since(t1))
return nil
}
用法
go run ops-sftp.go hosts 10.1.1.1,10.1.1.2 /workspace/test/w.txt /workspace/test/source.txt