Ai
1 Star 0 Fork 0

clearluo/gotools

Create your Gitee Account
Explore and code with more than 13.5 million developers,Free private repositories !:)
Sign up
文件
Clone or Download
util.go 17.14 KB
Copy Edit Raw Blame History
clearluo authored 2023-06-09 09:00 +08:00 . 变更 pprof
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
package util
import (
"archive/tar"
"archive/zip"
"bufio"
"bytes"
"compress/gzip"
"context"
"crypto/rand"
"encoding/binary"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"io/fs"
"io/ioutil"
"net"
"net/http"
"os"
"os/exec"
"path"
"path/filepath"
"reflect"
"regexp"
"runtime"
"strconv"
"strings"
"sync"
"time"
_ "net/http/pprof"
"gitee.com/clearluo/gotools/net/utilhttp"
"gitee.com/clearluo/gotools/zaplog"
"github.com/shirou/gopsutil/process"
"golang.org/x/text/encoding/simplifiedchinese"
"gitee.com/clearluo/gotools/log"
)
var (
processObj *process.Process
httpObj *http.Client
)
func init() {
var err error
processObj, err = process.NewProcess(int32(os.Getpid()))
if err != nil {
panic(err)
}
httpObj = utilhttp.NewHttpClient()
}
func randIntByCrypto() uint32 {
var n uint32
binary.Read(rand.Reader, binary.LittleEndian, &n)
return n
}
func AssertMarshal(v interface{}, params ...int) string {
b, _ := json.Marshal(v)
preNum := 0
if len(params) > 0 {
preNum = params[0]
}
if preNum == 0 || len(b) <= preNum {
return string(b)
}
return string(b[:preNum]) + "..."
}
func RandGenerate(n int) string {
buf := make([]byte, n)
rand.Read(buf)
return hex.EncodeToString(buf)
}
// 获取整点以来的秒数
func GetSecondFromHour() int64 {
return time.Now().Unix() % 3600
}
// 获取整天以来的秒数
func GetSecondFromDay() int64 {
return time.Now().Unix() - GetSecondByDay00()
}
// 获取整周以来的秒数
func GetSecondFromWeek() int64 {
day := int64(time.Now().Weekday())
return 86400*(day-1) + GetSecondFromDay()
}
// 获取整月以来的秒数
func GetSecondFromMonth() int64 {
day := int64(time.Now().Day())
return 86400*(day-1) + GetSecondFromDay()
}
// 获取当前日期(20170802)零点对应的Unix时间戳
func GetSecondByDay00() int64 {
timeStr := time.Now().Format("2006-01-02")
//使用Parse 默认获取为UTC时区 需要获取本地时区 所以使用ParseInLocation
t, _ := time.ParseInLocation("2006-01-02", timeStr, time.Local)
return t.Unix()
}
// 获取当前日期前后n天对应的日期证书,0代表获取当前日期整数
func GetDateByN(n int) int64 {
nTime := time.Now()
yesTime := nTime.AddDate(0, 0, n)
dayStr := yesTime.Format("20060102")
day, _ := strconv.ParseInt(dayStr, 10, 64)
return day
}
// 根据时间戳获取对应日期整数
func GetTDayByUnixTime(nowUnix int64) int64 {
if nowUnix < 1 {
return 0
}
tm := time.Unix(nowUnix, 0)
nowDay, err := strconv.ParseInt(tm.Format("20060102"), 10, 64)
if err != nil {
fmt.Println(err)
return 0
}
return nowDay
}
// 统计某函数执行时间
// 使用方式
// defer utils.Profiling("test")()
func Profiling(msg string) func() {
start := time.Now()
return func() {
zaplog.Infof(fmt.Sprintf("%s[%s]:%s", msg, "use", time.Since(start)))
}
}
// 判断文件夹是否存在
func PathExists(path string) bool {
_, err := os.Stat(path)
if err == nil {
return true
}
if os.IsNotExist(err) {
return false
}
return false
}
func GetFieldName(t reflect.Type) (map[string]string, error) {
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() != reflect.Struct {
err := fmt.Errorf("Check type error not Struct")
fmt.Println(err)
fmt.Println(err)
return nil, err
}
fieldNum := t.NumField()
result := make(map[string]string, 0)
for i := 0; i < fieldNum; i++ {
result[t.Field(i).Tag.Get("json")] = t.Field(i).Type.Name()
}
return result, nil
}
type TplJson struct {
Length int `json:"length"`
Data []map[string]interface{} `json:"data"`
}
func RunFuncName() string {
pc := make([]uintptr, 1)
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[0])
return f.Name()
}
func randIntn(n int) int {
return int(randIntByCrypto()) % n
}
func GetSignal() int {
if randIntn(2) == 0 {
return 1
}
return -1
}
// [min,max)
func RandMN(min int, max int) int {
x := max - min
n := randIntn(x) + min
return n
}
func GetMysqlParam(n int) string {
if n < 1 {
return ""
}
str := "?"
for i := 1; i < n; i++ {
str += ",?"
}
return str
}
func GetIndexByWeigth(data []int) int {
sum := 0
index := 0
for _, v := range data {
sum += v
}
randN := randIntn(sum)
sum = 0
for i, v := range data {
sum += v
if randN < sum {
index = i
break
}
}
return index
}
func GetPosInfo() (string, int) {
_, file, line, ok := runtime.Caller(1)
if !ok {
return "unknow", 0
}
return filepath.Base(file), line
}
func GetPosInfoStr() string {
_, file, line, ok := runtime.Caller(1)
if !ok {
return "[]"
}
return fmt.Sprintf("[%v:%v]\n", filepath.Base(file), line)
}
func FunFuncName() string {
pc := make([]uintptr, 1)
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[0])
return f.Name()
}
type Charset string
const (
UTF8 = Charset("UTF-8")
GB18030 = Charset("GB18030")
GBK = Charset("GBK")
)
func readCommond(ctx context.Context, wg *sync.WaitGroup, std io.ReadCloser, buf *bytes.Buffer) {
reader := bufio.NewReader(std)
defer wg.Done()
for {
select {
case <-ctx.Done():
return
default:
readString, err := reader.ReadString('\n')
if err != nil || err == io.EOF {
return
}
if runtime.GOOS == "windows" {
readString = ConvertByte2String([]byte(readString), "GB18030")
}
buf.WriteString(readString)
//fmt.Print(readString)
}
}
}
// 执行命令
func ExecCmd(dir string, str string) (string, error) {
if dir == "" {
dir = "./"
}
var out []byte
var err error
cmdSli := strings.Split(str, "|")
for _, cmdStr := range cmdSli {
cmdStr = strings.Trim(cmdStr, " ")
param := strings.Split(cmdStr, " ")
if len(param) < 1 {
continue
}
cmd := exec.Command(param[0], param[1:]...)
cmd.Dir = dir
cmd.Stdin = bytes.NewBuffer(out)
out, err = cmd.CombinedOutput()
if err != nil {
break
}
}
return string(out), err
}
func ExecCmd2(ctx context.Context, runDir string, cmd string) (string, error) {
var c *exec.Cmd
if runtime.GOOS == "windows" {
c = exec.CommandContext(ctx, "cmd", "/C", cmd) // windows
} else {
c = exec.CommandContext(ctx, "bash", "-c", cmd) // mac linux
}
c.Dir = runDir
stdout, err := c.StdoutPipe()
if err != nil {
return "", err
}
stderr, err := c.StderrPipe()
if err != nil {
return "", err
}
var wg sync.WaitGroup
// 因为有2个任务, 一个需要读取stderr 另一个需要读取stdout
stdoutBuf := &bytes.Buffer{}
stderrBuf := &bytes.Buffer{}
wg.Add(2)
go readCommond(ctx, &wg, stderr, stderrBuf)
go readCommond(ctx, &wg, stdout, stdoutBuf)
// 这里一定要用start,而不是run 详情请看下面的图
err = c.Start()
if err != nil {
return "", err
}
// 等待任务结束
wg.Wait()
if stderrBuf.Len() > 0 {
return stdoutBuf.String(), fmt.Errorf("%v", stderrBuf)
}
return stdoutBuf.String(), nil
}
func ConvertByte2String(byte []byte, charset Charset) string {
var str string
switch charset {
case GB18030:
var decodeBytes, _ = simplifiedchinese.GB18030.NewDecoder().Bytes(byte)
str = string(decodeBytes)
case GBK:
var decodeBytes, _ = simplifiedchinese.GBK.NewDecoder().Bytes(byte)
str = string(decodeBytes)
case UTF8:
fallthrough
default:
str = string(byte)
}
return str
}
var (
localIP string
onceIP sync.Once
localMac string
onceMac sync.Once
)
// 获取本机第一张网卡的mac地址
func GetLocalMac() string {
// 获取本机的MAC地址
onceMac.Do(func() {
interfaces, err := net.Interfaces()
if err != nil {
return
}
for _, inter := range interfaces {
if inter.HardwareAddr == nil {
continue
}
localMac = inter.HardwareAddr.String()
break
}
})
return localMac
}
// 获取本机ip
func GetIPv4() string {
onceIP.Do(func() {
addrs, err := net.InterfaceAddrs()
if err != nil {
return
}
for _, address := range addrs {
// 检查ip地址判断是否回环地址
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil && ipnet.IP.String() != "127.0.0.1" {
localIP = ipnet.IP.String()
return
}
}
}
},
)
return localIP
}
func GetPosInfoSplit() string {
_, file, line, ok := runtime.Caller(1)
if !ok {
return "[]||"
}
return "[" + filepath.Base(file) + ":" + strconv.Itoa(line) + "]||"
}
func GetBinDir() string {
t, _ := filepath.Abs(os.Args[0])
return strings.TrimRight(t, filepath.Base(t))
}
func GetBinDirNew() string {
t, _ := os.Executable()
return strings.TrimRight(strings.TrimRight(t, filepath.Base(t)), string(filepath.Separator))
}
func GetBinName() string {
t, _ := os.Executable()
return filepath.Base(t)
}
func GetPidByWindows(name string) (rets []int) {
pids, _ := process.Pids()
for _, pid := range pids {
pn, _ := process.NewProcess(pid)
pName, _ := pn.Name()
if pName == name {
rets = append(rets, int(pid))
}
}
return rets
}
func PidByBinName(binName string) []int {
binDir := GetBinDir()
binDir = strings.TrimRight(binDir, string(filepath.Separator))
//fmt.Printf("binDir:%v,binName:%v\n", binDir, binName)
retSli := make([]int, 0, 5)
//log.Warn("GetPid:", o.BinName)
if runtime.GOOS == "windows" {
return GetPidByWindows(binName)
}
cmdStr := fmt.Sprintf("pgrep %v -f", binName) // 进程名超过15个字符会查询失败,加-f参数可解决
//cmdStr := fmt.Sprintf("pgrep %v", binName)
result, err := ExecCmd(binDir, cmdStr)
if err != nil {
//log.Warnf("%v is not runing err:%v", binName, result)
return retSli
}
if strings.HasSuffix(result, "\n") {
result = strings.TrimRight(result, "\n")
}
pidSli := strings.Split(result, "\n")
//log.Debugf("pidSli:%v", pidSli)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
defer cancel()
for _, pidStr := range pidSli {
cmdStr = fmt.Sprintf("ls -l /proc/%v | grep cwd | awk '{print $11}'", pidStr)
runDir, err := ExecCmd2(ctx, binDir, cmdStr)
if err != nil {
log.Debug(err)
continue
}
if strings.HasSuffix(runDir, "\n") {
runDir = strings.TrimRight(runDir, "\n")
}
if runDir != binDir {
//fmt.Printf("pidStr:%v runDir:%v o.RunDir:%v\n", pidStr, runDir, binDir)
log.Debugf("runDir:%v o.RunDir:%v", runDir, binDir)
continue
}
pid, _ := strconv.Atoi(pidStr)
if pid <= 1 {
log.Debugf("pid:%v", pid)
continue
}
if pid == os.Getpid() {
continue
}
retSli = append(retSli, pid)
}
return retSli
}
func MonitorStatus(interTime time.Duration, param ...func() string) {
defer func() {
if err := recover(); err != nil {
zaplog.Warn("MonitorStatus err:", err)
}
}()
tick := time.NewTicker(interTime)
memorySize := 0.0
mInfo := &process.MemoryInfoStat{}
memStatus := &runtime.MemStats{}
buf := bytes.Buffer{}
var err error
for {
buf.Reset()
select {
case <-tick.C:
mInfo, err = processObj.MemoryInfo()
if err == nil {
memorySize = float64(mInfo.RSS) / 1024.0 / 1024.0
}
runtime.ReadMemStats(memStatus)
for _, v := range param {
buf.WriteString(" " + v())
}
zaplog.Infof("current Goroutine:%-6d Memory:%.2fMb Heap:%.2fMb Stack:%.2fMb%v",
runtime.NumGoroutine(),
memorySize,
float64(memStatus.HeapInuse)/1024.0/1024.0,
float64(memStatus.StackInuse)/1024.0/1024.0,
buf.String())
}
}
}
func printPprof(pprofPort string) {
urlStr := "http://127.0.0.1:" + pprofPort + "/debug/pprof/goroutine?debug=1"
req, err := http.NewRequest("GET", urlStr, nil)
if err != nil {
zaplog.Warn(err)
return
}
req.Header.Add("Authorization", "Basic Z2FtZWFjY291bnQ6SElzSE9QRVJ2ZVJBbWF0aA==")
resp, err := httpObj.Do(req)
if err != nil {
zaplog.Warn(err)
return
}
defer resp.Body.Close()
b, err := io.ReadAll(resp.Body)
if err != nil {
zaplog.Warn(err)
return
}
zaplog.Warnf("printPprof[%v]:%v", urlStr, string(b))
}
// RunPprof addr ip:port
func RunPprof(addr string) {
defer func() {
if err := recover(); err != nil {
zaplog.Warn("RunPprof err:", err)
} else {
zaplog.Info("RunPprof is stop")
}
}()
if err := http.ListenAndServe(addr, nil); err != nil {
zaplog.Warn(err)
}
}
func GetBody(r *http.Request) []byte {
b := []byte{}
b, _ = ioutil.ReadAll(r.Body)
return b
}
func FuncName() string {
pc := make([]uintptr, 1)
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[0])
return filepath.Base(f.Name())
}
func TarGz(src string, dest string) error {
// 打开文件夹
dir, err := os.Open(src)
if err != nil {
return err
}
defer dir.Close()
// file write
fw, err := os.Create(dest)
if err != nil {
return err
}
defer fw.Close()
// gzip write
gw := gzip.NewWriter(fw)
defer gw.Close()
// tar write
tw := tar.NewWriter(gw)
defer tw.Close()
// 读取文件列表
fis, err := dir.Readdir(0)
if err != nil {
return err
}
// 遍历文件列表
for _, fi := range fis {
// 逃过文件夹, 我这里就不递归了
if fi.IsDir() {
continue
}
// 打印文件名称
//fmt.Println(fi.Name())
// 打开文件
fr, err := os.Open(dir.Name() + "/" + fi.Name())
if err != nil {
return err
}
defer fr.Close()
// 信息头
h := new(tar.Header)
h.Name = fi.Name()
h.Size = fi.Size()
h.Mode = int64(fi.Mode())
h.ModTime = fi.ModTime()
// 写信息头
err = tw.WriteHeader(h)
if err != nil {
return err
}
// 写文件
_, err = io.Copy(tw, fr)
if err != nil {
return err
}
}
return nil
}
func IPUint32ToIP(intIP uint32) net.IP {
return net.IPv4(byte((intIP>>24)&0xFF), byte((intIP>>16)&0xFF), byte((intIP>>8)&0xFF), byte(intIP&0xFF))
}
func IPIPToUint32(ipnr net.IP) (sum uint32, err error) {
return IPStringToUint32(ipnr.String())
}
func IPStringToUint32(ipString string) (sum uint32, err error) {
bits := strings.Split(ipString, ".")
if len(bits) != 4 {
return sum, errors.New("ip format err")
}
b0, _ := strconv.Atoi(bits[0])
b1, _ := strconv.Atoi(bits[1])
b2, _ := strconv.Atoi(bits[2])
b3, _ := strconv.Atoi(bits[3])
sum += uint32(b0) << 24
sum += uint32(b1) << 16
sum += uint32(b2) << 8
sum += uint32(b3)
return
}
func HideStar(str string) (result string) {
if str == "" {
return "***"
}
nameRune := []rune(str)
// 邮箱
if strings.Contains(str, "@") {
res := strings.Split(str, "@")
if len(res[0]) < 4 {
result = "***@" + res[1]
} else {
result = string(nameRune[:3]) + "***@" + res[1]
}
return result
}
reg := `^[0-9]\d{9}$`
rgx := regexp.MustCompile(reg)
mobileMatch := rgx.MatchString(str)
// 手机号
if mobileMatch {
return string(nameRune[:3]) + "***" + string(nameRune[7:11])
}
// 普通字符串
lens := len(nameRune)
if lens < 4 {
result = "***"
} else if lens < 9 {
result = string(nameRune[:2]) + "***" + string(nameRune[lens-2:])
} else {
result = string(nameRune[:4]) + "***" + string(nameRune[lens-4:])
}
return result
}
//func Substr2(str string, start int, end int) string {
// rs := []rune(str)
// return string(rs[start:end])
//}
func PrintEncode(str string) (newStr string) {
n := len(str)
if n <= 3 {
return str
} else {
return str[:4] + "***" + str[n-4:]
}
}
func Zip(zipPath string, paths ...string) error {
// create zip file
if err := os.MkdirAll(filepath.Dir(zipPath), os.ModePerm); err != nil {
return err
}
archive, err := os.Create(zipPath)
if err != nil {
return err
}
defer archive.Close()
// new zip writer
zipWriter := zip.NewWriter(archive)
defer zipWriter.Close()
// traverse the file or directory
for _, srcPath := range paths {
// remove the trailing path separator if path is a directory
srcPath = strings.TrimSuffix(srcPath, string(os.PathSeparator))
// visit all the files or directories in the tree
err = filepath.Walk(srcPath, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}
// create a local file header
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
// set compression
header.Method = zip.Deflate
// set relative path of a file as the header name
header.Name, err = filepath.Rel(filepath.Dir(srcPath), path)
if err != nil {
return err
}
if info.IsDir() {
header.Name += string(os.PathSeparator)
}
// create writer for the file header and save content of the file
headerWriter, err := zipWriter.CreateHeader(header)
if err != nil {
return err
}
if info.IsDir() {
return nil
}
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()
_, err = io.Copy(headerWriter, f)
return err
})
if err != nil {
return err
}
}
return nil
}
// Unzip decompresses a zip file to specified directory.
// Note that the destination directory don't need to specify the trailing path separator.
func Unzip(zipPath, dstDir string) error {
// open zip file
reader, err := zip.OpenReader(zipPath)
if err != nil {
return err
}
defer reader.Close()
for _, file := range reader.File {
if err := unzipFile(file, dstDir); err != nil {
return err
}
}
return nil
}
func unzipFile(file *zip.File, dstDir string) error {
// create the directory of file
filePath := path.Join(dstDir, file.Name)
if file.FileInfo().IsDir() {
if err := os.MkdirAll(filePath, os.ModePerm); err != nil {
return err
}
return nil
}
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
return err
}
// open the file
r, err := file.Open()
if err != nil {
return err
}
defer r.Close()
// create the file
w, err := os.Create(filePath)
if err != nil {
return err
}
defer w.Close()
// save the decompressed file content
_, err = io.Copy(w, r)
return err
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/clearluo/gotools.git
git@gitee.com:clearluo/gotools.git
clearluo
gotools
gotools
v1.4.2

Search