package main
import (
"archive/zip"
"encoding/json"
"flag"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
"time"
"github.com/jlaffaye/ftp"
)
type Config struct {
Endpoint string `json:"endpoint"`
UserName string `json:"username"`
PassWord string `json:"password"`
FtpAddr string `json:"ftpaddr"`
RootDir string `json:"rootdir"`
PushAddr string `json:"pushaddr"`
CreateDir bool `json:"createdir"`
ZipCheck bool `json:"zipcheck"`
}
var (
config Config
cfgpath string
filepath string
)
func init() {
flag.StringVar(&cfgpath, "cfg", "", "-cfg cfg.json 从文件读取配置")
flag.StringVar(&filepath, "f", "", "-f backup.zip 指定要上传的文件")
flag.StringVar(&config.UserName, "u", "", "-u root 指定ftp登录名称")
flag.StringVar(&config.PassWord, "p", "", "-p root 指定ftp登录密码")
flag.StringVar(&config.FtpAddr, "a", "", "-a 192.168.0.1:21 指定ftp登录地址")
flag.StringVar(&config.PushAddr, "P", "", "-P 127.0.0.1:1988 指定ftp登录密码")
flag.StringVar(&config.Endpoint, "e", "", "-e endpoint 指定当前Endpoint名称")
flag.StringVar(&config.RootDir, "r", "", "-r /backup 指定登录的根目录")
flag.BoolVar(&config.CreateDir, "c", false, "-c 按日期创建目录")
flag.BoolVar(&config.ZipCheck, "z", false, "-z 检查是否有效的zip文件")
example := flag.Bool("example", false, "-example 生成配置文件")
flag.Parse()
if *example {
File, err := os.Create("cfg.json")
if err == nil {
File.Write([]byte(`{
"endpoint":"",
"username":"user",
"password":"password",
"ftpaddr":"127.0.0.1:21",
"rootdir":"/backup",
"pushaddr":"",
"createdir":true,
"zipcheck":true
}`))
File.Close()
} else {
log.Fatalf("Create example file error:%s\n", err.Error())
}
os.Exit(0)
}
}
type result struct {
Path string `json:"path"`
Reult bool `json:"result"`
}
type MetricValue struct {
Endpoint string `json:"endpoint"`
Metric string `json:"metric"`
Value int `json:"value"`
Step int64 `json:"step"`
Type string `json:"counterType"`
Tags string `json:"tags"`
Timestamp int64 `json:"timestamp"`
}
func main() {
//创建日志文件,以增加模式打开
logFile, err := os.OpenFile("run.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
if err == nil {
log.SetOutput(logFile)
}
var res result
//设置程序结束执行的函数
defer func() {
//判断Push地址是不是为空,如果不为空则发一条监控数据到指定的接口
if config.PushAddr != "" {
var Met = []MetricValue{{Endpoint: config.Endpoint, Metric: "sqlserver.backupload", Value: 0, Step: 86400, Type: "GAUGE", Timestamp: time.Now().Unix()}}
if res.Reult {
Met[0].Value = 1
}
buf, _ := json.Marshal(Met)
resp, err := http.Post(config.PushAddr, "application/json", strings.NewReader(string(buf)))
if err == nil {
if resp.StatusCode != 200 {
log.Printf("Post return status code %d\n", resp.StatusCode)
}
} else {
log.Printf("Post warnning error:%s\n", err.Error())
}
}
//将执行的结果以标准的json格式写入文件,
File, err := os.OpenFile(time.Now().Format("20060102")+"_reult.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
if err != nil {
log.Fatalf("Open result file error:%s\n", err.Error())
}
buf, _ := json.Marshal(res)
File.Write(buf)
File.Write([]byte("\r\n"))
File.Close()
}()
res.Path = filepath
//处理要发送的文件路径,用','分割
files := strings.Split(strings.TrimSpace(filepath), ",")
if len(files) == 0 {
log.Println("Upload file can't empty")
return
}
//解析json配置文件
if cfgpath != "" {
if err := parsrconfig(cfgpath, &config); err != nil {
log.Printf("Parse config error:%s\n", err.Error())
return
}
}
//检测一下配置是否正确
if checkconfig(config) {
log.Println("Invalid config")
return
}
//遍历待上传的文件路径检测是否为有效的zip
if config.ZipCheck {
for _, path := range files {
rc, err := zip.OpenReader(path)
if err != nil {
log.Printf("Invalid zip file:%s\n", err.Error())
return
}
rc.Close()
}
}
//上传文件
err = upload(config, files)
if err == nil {
res.Reult = true
} else {
log.Printf("Upload file error:%s\n", err.Error())
}
}
func parsrconfig(cfgpath string, cfg *Config) error {
buf, err := ioutil.ReadFile(cfgpath)
if err == nil {
err = json.Unmarshal(buf, cfg)
}
return err
}
func checkconfig(cfg Config) bool {
if cfg.PushAddr != "" {
if cfg.Endpoint == "" {
return true
}
}
return cfg.FtpAddr == "" || cfg.UserName == "" || cfg.PassWord == ""
}
func upload(cfg Config, paths []string) error {
//连接远程地址
remote, err := ftp.Dial(cfg.FtpAddr)
if err != nil {
return err
}
defer remote.Quit()
//开始登录认证
err = remote.Login(cfg.UserName, cfg.PassWord)
if err != nil {
return err
}
var rootpath string = "/"
if cfg.RootDir != "" {
rootpath = cfg.RootDir
}
if rootpath[len(rootpath)-1] != '/' {
rootpath += "/"
}
//按当天的日期创建目录
if cfg.CreateDir {
rootpath += time.Now().Format("20060102") + "/"
remote.MakeDir(rootpath)
}
//切换到目录
err = remote.ChangeDir(rootpath)
if err != nil {
return err
}
//遍历待上传的文件开始上传
for _, path := range paths {
//打开文件
File, err := os.Open(path)
if err != nil {
return err
}
//开始上传
err = remote.Stor(rootpath+path, File)
File.Close()
if err != nil {
return err
}
}
return nil
}
Go1.9帮同事写个备份上传小程序,带推告警到open-falcon功能
最新推荐文章于 2024-08-08 07:52:41 发布