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功能
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.