Go1.5从文件读取密码,然后到远端下载文件的小实例.(通过sftp协议下载)

package main

import (
	"bufio"
	"fmt"
	"golang.org/x/crypto/ssh"
	"golang.org/x/crypto/ssh/agent"
	"io"
	"log"
	"net"
	"os"
	"path/filepath"
	"regexp"
	"sftp"
	"strings"
)

func main() {
	if len(os.Args) != 3 {
		fmt.Println("参数不正确:")
		fmt.Printf("上传文件:%s %s %s\n", os.Args[0], "/data/Test.txt", "127.0.0.1:/mnt/")
		fmt.Printf("下载文件:%s %s %s\n", os.Args[0], "127.0.0.1:/mnt/Test.txt", "/data/")
		os.Exit(1)
	}
	_, err := os.Stat(os.Args[1])
	if err != nil {
		get()
		return
	}
	push()
}

func get() {
	localpath := strings.Replace(os.Args[2], `\`, `/`, 20)
	re, _ := regexp.Compile(`((([1-9]?|1\d)\d|2([0-4]\d|5[0-5]))\.){3}(([1-9]?|1\d)\d|2([0-4]\d|5[0-5]))`)
	if re.MatchString(localpath) {
		fmt.Println("检查文件源地址.")
		return
	}
	list := strings.Split(os.Args[1], ":")
	if len(list) != 2 {
		fmt.Println("检查文件源地址.")
		return
	}
	fmt.Println("文件下载.")
	Sftp(list[0], list[1], localpath, "get")
}

func push() {
	list := strings.Split(os.Args[2], ":")
	if len(list) != 2 {
		fmt.Println("检查文件源地址.")
		return
	}
	fmt.Println("文件推送.")
	localpath := strings.Replace(list[1], `\`, `/`, 20)
	Sftp(list[0], os.Args[1], localpath, "push")
}

func Sftp(ip, path, localpath, action string) {
	var auths []ssh.AuthMethod
	if aconn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil {
		auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(aconn).Signers))

	}
	auth_list := parse("passlist", ip)
	if len(auth_list) == 0 {
		log.Println("获取用户和密码失败.")
		os.Exit(-1)
	}
	auths = append(auths, ssh.Password(auth_list[2]))

	config := ssh.ClientConfig{
		User: auth_list[1],
		Auth: auths,
	}
	addr := fmt.Sprintf("%s:%s", ip, auth_list[3])
	conn, err := ssh.Dial("tcp", addr, &config)
	if err != nil {
		log.Fatalf("unable to connect to [%s]: %v", addr, err)
	}
	defer conn.Close()
	c, err := sftp.NewClient(conn, sftp.MaxPacket(6e9))
	if err != nil {
		log.Fatalf("unable to start sftp subsytem: %v", err)
	}
	defer c.Close()
	switch action {
	case "get":
		fs, e := c.Open(path)
		if e != nil {
			log.Println(e)
			os.Exit(-1)
		}
		filename := filepath.Base(path)
		info, _ := fs.Stat()
		File, err := os.Create(fmt.Sprintf(`%s/%s`, strings.TrimRight(localpath, `/`), filename))
		if err != nil {
			log.Println(err)
			os.Exit(-1)
		}
		log.Println("保存路径:", fmt.Sprintf(`%s/%s`, strings.TrimRight(localpath, `/`), filename))
		defer File.Close()
		io.Copy(File, io.LimitReader(fs, info.Size()))
	case "push":
		filename := filepath.Base(path)
		fs, err := c.Create(fmt.Sprintf(`%s/%s`, strings.TrimRight(localpath, `/`), filename))
		if err != nil {
			log.Println(err)
			os.Exit(-1)
		}
		defer fs.Close()
		log.Println("保存路径:", fmt.Sprintf(`%s/%s`, strings.TrimRight(localpath, `/`), filename))
		File, err := os.Open(path)
		if err != nil {
			log.Println(err)
			os.Exit(-1)
		}
		defer File.Close()
		io.Copy(io.MultiWriter(fs), File)
	}
}

func parse(cfg, ip string) []string {
	File, err := os.Open(cfg)
	if err != nil {
		log.Println("打开配置文件失败.")
		os.Exit(-1)
	}
	defer File.Close()
	buf := bufio.NewReader(File)
	for {
		line, _, err := buf.ReadLine()
		if err != nil {
			if err == io.EOF {
				break
			}
			fmt.Println(err)
			break
		}
		if strings.Contains(string(line), ip) {
			return split(string(line))
		}
	}
	return []string{}
}

func split(str string) []string {
	var l []string
	list := strings.Split(str, " ")
	for _, v := range list {
		if len(v) == 0 {
			continue
		}
		if strings.Contains(v, "	") {

			list := strings.Split(v, "	")
			for _, v := range list {
				if len(v) == 0 {
					continue
				}
				l = append(l, v)
			}
			continue
		}
		l = append(l, v)
	}
	return l
}

你可能感兴趣的:(Golang)