golang日志中心取日志代码分享

本文介绍了一个使用HTTP POST请求实现文件复制与打包的过程,包括请求参数设置、文件路径匹配与复制逻辑,以及如何通过JSON格式传递任务详情。
/*
请求使用方法:
	Id要唯一
	Tag:有两个值"listfile,getfile,或者"
	源地址必须是在:192.168.0.0/24,172.18.0.0/24,10.0.0.0/24网段.不接受公网地址.

 event := job{Id: "cp_19216823", Name: []string{`game/logs/log`,
		`gate/logs/log`, `game-fight`, `mail/logs/log`, `room-manage/logs/log`, `/oem8.log`},
		Path: `C:\test\server`, Tag: "listfile"}
	b, _ := json.Marshal(event)
	buf := bytes.NewReader(b)
	resp, err := http.Post("http://172.18.80.247:1789/", bodyType, buf)
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	b, _ = ioutil.ReadAll(resp.Body)
	fmt.Println(string(b))
*/

package main

import (
	"archive/zip"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"
)

func main() {
	go Server(":1789")
	go Init()
	var x job = job{Id: "cp_19216823", Name: []string{`game/logs/log`,
		`gate/logs/log`, `game-fight`, `mail/logs/log`, `room-manage/logs/log`, `C:\oem8.log`},
		Path: `C:\test\server`, Tag: ""}
	b, _ := json.Marshal(x)
	buf := bytes.NewReader(b)
	resp, err := http.Post("http://172.18.80.247:1789/", bodyType, buf)
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	b, _ = ioutil.ReadAll(resp.Body)
	fmt.Println(string(b))
	time.Sleep(3e9)
}

var (
	JobChan chan *job = make(chan *job, 5)
	stdout  io.Writer = os.Stdout
	debug   bool      = true
)

func init() {
	os.MkdirAll(tempDir, 0644)
}

func Init() {
	for {
		j := <-JobChan
		go j.Run()
	}
}

const (
	zone     int64 = +8
	bodyType       = "application/x-www-form-urlencoded"
	tempDir        = "tmp"
)

type job struct {
	Id   string   `json:id`
	Name []string `json:name`
	Path string   `json:path`
	Tag  string   `json:"tag"`
	temp string   `json:tempfile`
}

func (self *job) Init() {
	self.Path = filepath.ToSlash(self.Path)
	if !filepath.HasPrefix(self.Path, "/") {
		self.Path = self.Path + "/"
	}
	self.temp = tempDir + "/" + self.Id + "/"
	os.MkdirAll(self.temp, 0644)
}

//返回两个值,分别为未成功copy的路径,另外一个是成功copy的路径
func (self *job) Copy() ([]string, []string) {
	var uncopylist, pathlist []string
	for _, v := range self.Name {
		v = filepath.ToSlash(v)
		var path, dst string
		if filepath.IsAbs(v) {
			list := strings.Split(v, "/")
			if len(list) <= 1 {
				continue
			}
			dst = self.temp + strings.Join(list[1:], "/")
			pathlist = append(pathlist, dst)
			err := copyFile(v, dst)
			if err != nil {
				if debug {
					currentLine(err)
				}
				uncopylist = append(uncopylist, v)
			}
			continue
		}
		path = self.Path + v
		basedir := filepath.ToSlash(filepath.Dir(v))
		if basedir != filepath.Base(v) {
			os.MkdirAll(self.temp+basedir, 0644)
		}
		dst = self.temp + v
		pathlist = append(pathlist, dst)
		err := copyFile(path, dst)
		if err != nil {
			if debug {
				currentLine(err)
			}
			uncopylist = append(uncopylist, v)
			continue
		}
	}
	return uncopylist, pathlist
}

func (self *job) ListFile() map[string][]string {
	var m map[string][]string = make(map[string][]string)
	for _, v := range self.Name {
		var list []string
		v = filepath.ToSlash(v)
		if filepath.IsAbs(v) {
			_, err := os.Stat(v)
			if err != nil {
				if debug {
					currentLine(err)
				}
				continue
			}
			m[v] = append(list, v)
			continue
		}
		path := self.Path + v
		info, err := os.Stat(path)
		if err != nil {
			if debug {
				currentLine(err)
			}
			continue
		}
		if !info.IsDir() {
			list = append(list, path)
			m[path] = list
			continue
		}
		l, err := ioutil.ReadDir(path)
		if err != nil {
			if debug {
				currentLine(err)
			}
			continue
		}
		for _, name := range l {
			list = append(list, name.Name())
		}
		m[path] = list
	}
	return m
}

func (self *job) Run() {
	_, path := self.Copy()
	if debug {
		currentLine(path)
	}
	switch self.Tag {
	case "getfile":
		tZip(tempDir+"/"+self.Id, tempDir+"/"+self.Id+".zip")
		os.RemoveAll(tempDir + "/" + self.Id)
	default:
	}
}

func copyFile(src, dst string) error {
	sFile, err := os.Open(src)
	if err != nil {
		return err
	}
	defer sFile.Close()
	dFile, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer dFile.Close()
	io.Copy(dFile, sFile)
	return nil
}

func tZip(source, target string) error {
	zipfile, err := os.Create(target)
	if err != nil {
		return err
	}
	defer zipfile.Close()
	archive := zip.NewWriter(zipfile)
	defer archive.Close()

	return filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		header, err := zip.FileInfoHeader(info)
		if err != nil {
			return err
		}
		if !info.IsDir() {
			header.Method = zip.Deflate
		}
		header.SetModTime(time.Unix(info.ModTime().Unix()+(zone*60*60), 0))
		header.Name = path
		writer, err := archive.CreateHeader(header)
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}
		file, err := os.Open(path)
		if err != nil {
			return err
		}
		defer file.Close()
		_, err = io.Copy(writer, file)
		return err
	})
}

const (
	ForbiddenAccess = 403
	MarshalError    = 550
	UnmarshalError  = 551
	ReadBodyError   = 552
)

func route(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()
	ip, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil || !ipIsLanIP(ip) {
		http.Error(w, "ForbiddenAccess", ForbiddenAccess)
		return
	}
	buf, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "ReadBodyError", ReadBodyError)
		return
	}
	Job := new(job)
	err = json.Unmarshal(buf, Job)
	if err != nil {
		http.Error(w, "UnmarshalError", UnmarshalError)
		return
	}
	Job.Init()
	if Job.Tag == "listfile" {
		buf, err = json.Marshal(Job.ListFile())
		if err != nil {
			http.Error(w, "MarshalError", MarshalError)
			return
		}
		w.Write(buf)
		return
	} else {
		JobChan <- Job
		w.Write([]byte("job is running,wait a moment"))
	}
}

func Server(ip string) {
	http.HandleFunc("/", route)
	http.ListenAndServe(ip, nil)
}

//安全起见,设置允许的网段,只允许内网.
var (
	mask  net.IPMask = net.CIDRMask(16, 32)
	IP192 net.IPNet  = net.IPNet{net.ParseIP("192.168.0.0"), mask}
	IP172 net.IPNet  = net.IPNet{net.ParseIP("172.18.0.0"), mask}
	IP10  net.IPNet  = net.IPNet{net.ParseIP("10.0.0.0"), mask}
)

func ipIsLanIP(str string) bool {
	ip := net.ParseIP(str)
	return IP192.Contains(ip) || IP172.Contains(ip) || IP10.Contains(ip)
}

func currentLine(info interface{}) {
	_, file, line, ok := runtime.Caller(1)
	if ok {
		fmt.Fprintf(stdout, "File:%s Line:%d \nInfo: %v\n", file, line, info)
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值