嵌入式linux之go语言开发(六)几行代码实现终端的远程日志诊断

简介: 嵌入式linux之go语言开发(六)几行代码实现终端的远程日志诊断

日志是应用的镜子,可以发现应用中的问题,重要性不言而喻。


以往设备有问题了,是如何诊断的?我们是现场人员到现场,又是配合抓包,又是配合提供机器日志,效率极其低下。


如今都物联网时代了,能让数据跑路的还让人去跑路,不合适吧。


日志应能实现手工触发上送,或应用中出现严重问题时主动上送,或者远程控制其是否上送。


试想,如果能让问题出现在被客户发现之前,提前被开发人员获知,主动的解决问题,那么无疑提高了产品的竞争力和口碑。为杜绝问题造成的严重性而未及时发现提供先机。


当某天发现一机器偶然吐出一异常的bug日志时,且这日志暴露的问题若不解决将造成严重后果,而你恰好在你的邮箱里看到,这就在不知不觉中主动发现了问题。不用运维人员去找你,客户去找你,机器向你求救了。那么,救救它吧。


以下为在嵌入式linux上实现的一小功能,对终端产生的日志文件进行zip压缩并上送到后台FTP服务器中。


几行代码,轻松实现。又一次体现使用 go开发嵌入式linux应用的强大之处。


若要用c去做,那么呵呵,可以试试。


package main
import (
  "archive/zip"
  "flag"
  "fmt"
  "io"
  "log"
  "os"
  "strings"
  "github.com/dutchcoders/goftp"
  "github.com/larspensjo/config"
)
var (
  ftp     *goftp.FTP
  conFile        = flag.String("ftpcfg", "/ftpcfg.ini", "config file")
  Server  string = "127.0.0.1:21"
  User    string = ""
  Pwd     string = ""
)
func checkErr(err error) {
  if err != nil {
    fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
  }
}
/**
@files:需要压缩的文件
@compreFile:压缩之后的文件
*/
func CompressZip(files []*os.File, zipfileName string) (err error) {
  zipfile, err := os.Create(zipfileName)
  if err != nil {
    return err
  }
  defer zipfile.Close()
  zw := zip.NewWriter(zipfile)
  defer zw.Close()
  for _, file := range files {
    err := compressZip(file, zw)
    if err != nil {
      return err
    }
    file.Close()
  }
  return nil
}
/**
功能:压缩文件
@file:压缩文件
@prefix:压缩文件内部的路径
@tw:写入压缩文件的流
*/
func compressZip(file *os.File, zw *zip.Writer) error {
  info, err := file.Stat()
  if err != nil {
    log.Println("压缩文件失败:", err.Error())
    return err
  }
  log.Println("filesize:", info.Size()/1024, "kb")
  // 获取压缩头信息
  head, err := zip.FileInfoHeader(info)
  if err != nil {
    log.Println("压缩文件失败:", err.Error())
    return err
  }
  // 指定文件压缩方式 默认为 Store 方式 该方式不压缩文件 只是转换为zip保存
  head.Method = zip.Deflate
  fw, err := zw.CreateHeader(head)
  if err != nil {
    log.Println("压缩文件失败:", err.Error())
    return err
  }
  // 写入文件到压缩包中
  _, err = io.Copy(fw, file)
  file.Close()
  if err != nil {
    log.Println("压缩文件失败:", err.Error())
    return err
  }
  return nil
}
func main() {
  log.Println("Hello Go")
  defer func() {
    if r := recover(); r != nil {
      log.Printf("crash occurred!capture:%s\n", r)
    }
  }()
  var fname string
  flag.StringVar(&fname, "fname", "", "file name")
  flag.Parse()
  flag.Usage()
  //获取当前路径
  file, _ := os.Getwd()
  cfg, err := config.ReadDefault(file + *conFile)
  checkErr(err)
  //获取配置文件中的配置项
  Server, err = cfg.String("SERVERCONFIG", "Server")
  User, err = cfg.String("USER", "User")
  Pwd, err = cfg.String("USER", "Pwd")
  //压缩ZIP
  var filezips []*os.File
  var filezip *os.File
  if filezip, err = os.Open(fname); err != nil {
    panic(err)
  }
  filezips = append(filezips, filezip)
  log.Println("begin compressZip...")
  err = CompressZip(filezips, fname+".zip")
  if err != nil {
    panic(err)
  }
  log.Println("compressZip ok!,name=" + fname + ".zip")
  log.Println("User:" + User)
  log.Println("->begin connect server:" + Server)
  // For debug messages: goftp.ConnectDbg("ftp.server.com:21")
  if ftp, err = goftp.ConnectDbg(Server); err != nil {
    panic(err)
  }
  //ftp.debug = true
  defer ftp.Close()
  log.Println("->Successfully connected !!")
  // Username / password authentication
  if err = ftp.Login(User, Pwd); err != nil {
    panic(err)
  }
  log.Println("->Login success!")
  if err = ftp.Cwd("/"); err != nil {
    panic(err)
  }
  var curpath string
  if curpath, err = ftp.Pwd(); err != nil {
    panic(err)
  }
  log.Printf("Current path: %s\n", curpath)
  // Upload a file
  var fileup *os.File
  if fileup, err = os.Open(fname + ".zip"); err != nil {
    panic(err)
  }
  log.Println("->begin upload file...")
  info, err := fileup.Stat()
  if err != nil {
    panic(err)
  }
  log.Println("upload filesize:", info.Size()/1024, "kb")
  fpath := fname + ".zip"
  lastidx := strings.LastIndex(fname+".zip", "/")
  if lastidx != -1 {
    fpath = fname[lastidx:] + ".zip"
  }
  log.Printf("fpath:%s\n", fpath)
  if err := ftp.Stor(fpath, fileup); err != nil {
    panic(err)
  }
  log.Println("->upload file over!")
  err = os.Remove(fname + ".zip") //上传成功,删除zip文件
  if err != nil {
    log.Println("file remove Error!")
    panic(err)
  }
}


编译与使用:


GOOS=linux GOARCH=arm GOARM=7 go build ftp.go
ftp -fname=/log/log_b503_20190730.log
root@b_lcd:/app/opt
./ftp -fname=/log/log_b503_20190730.log
Hello Go
Usage of ./ftp:
  -fname string
        file name
  -ftpcfg string
        config file (default "/ftpcfg.ini")
User:qq8864
->begin connect server:015.3vftp.com:21
2019/07/30 17:44:08 begin receiveLine...
2019/07/30 17:44:09 < 220 Serv-U FTP Server v6.4 for WinSock ready...
2019/07/30 17:44:09 receiveLine over!
2019/07/30 17:44:09 220 Serv-U FTP Server v6.4 for WinSock ready...
->Successfully connected !!
2019/07/30 17:44:09 > USER qq8864
2019/07/30 17:44:09 begin receiveLine...
2019/07/30 17:44:09 < 331 User name okay, need password.
2019/07/30 17:44:09 receiveLine over!
2019/07/30 17:44:09 > PASS sars1212
2019/07/30 17:44:09 begin receiveLine...
2019/07/30 17:44:09 < 230 User logged in, proceed.
2019/07/30 17:44:09 receiveLine over!
->Login success!
2019/07/30 17:44:09 > CWD /
2019/07/30 17:44:09 begin receiveLine...
2019/07/30 17:44:09 < 250 Directory changed to /
2019/07/30 17:44:09 receiveLine over!
2019/07/30 17:44:09 > PWD
2019/07/30 17:44:09 begin receiveLine...
2019/07/30 17:44:09 < 257 "/" is current directory.
2019/07/30 17:44:09 receiveLine over!
Current path: /
->begin upload file...
fpath:/log_b503_20190730.log
2019/07/30 17:44:09 > TYPE I
2019/07/30 17:44:09 begin receiveLine...
2019/07/30 17:44:11 < 200 Type set to I.
2019/07/30 17:44:11 receiveLine over!
2019/07/30 17:44:11 > PASV
2019/07/30 17:44:11 begin receiveLine...
2019/07/30 17:44:11 < 227 Entering Passive Mode (52,128,243,181,6,1)
2019/07/30 17:44:11 receiveLine over!
2019/07/30 17:44:11 > STOR /log_b503_20190730.log
2019/07/30 17:44:11 Connecting to 015.3vftp.com:1537
2019/07/30 17:44:11 begin receiveLine...
2019/07/30 17:44:11 < 150 Opening BINARY mode data connection for log_b503_20190730.log.
2019/07/30 17:44:11 receiveLine over!
2019/07/30 17:44:11 a1:150 Opening BINARY mode data connection for log_b503_20190730.log.
2019/07/30 17:44:11 begin receiveLine...
2019/07/30 17:44:13 < 226-Maximum disk quota limited to 102400 kBytes
2019/07/30 17:44:13 receiveLine over!
2019/07/30 17:44:13 begin receiveLine...
2019/07/30 17:44:13 <     Used disk quota 64 kBytes, available 102335 kBytes
2019/07/30 17:44:13 receiveLine over!
2019/07/30 17:44:13 begin receiveLine...
2019/07/30 17:44:13 < 226 Transfer complete.
2019/07/30 17:44:13 receiveLine over!
2019/07/30 17:44:13 a2:226-Maximum disk quota limited to 102400 kBytes
    Used disk quota 64 kBytes, available 102335 kBytes
226 Transfer complete.
->upload file over!


相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
2月前
|
算法 Java Go
【GoGin】(1)上手Go Gin 基于Go语言开发的Web框架,本文介绍了各种路由的配置信息;包含各场景下请求参数的基本传入接收
gin 框架中采用的路优酷是基于httprouter做的是一个高性能的 HTTP 请求路由器,适用于 Go 语言。它的设计目标是提供高效的路由匹配和低内存占用,特别适合需要高性能和简单路由的应用场景。
263 4
|
4月前
|
数据采集 数据挖掘 测试技术
Go与Python爬虫实战对比:从开发效率到性能瓶颈的深度解析
本文对比了Python与Go在爬虫开发中的特点。Python凭借Scrapy等框架在开发效率和易用性上占优,适合快速开发与中小型项目;而Go凭借高并发和高性能优势,适用于大规模、长期运行的爬虫服务。文章通过代码示例和性能测试,分析了两者在并发能力、错误处理、部署维护等方面的差异,并探讨了未来融合发展的趋势。
363 0
|
2月前
|
JavaScript 前端开发 Java
【GoWails】Go做桌面应用开发?本篇文章带你上手Wails框架!一步步带你玩明白前后端双端的数据绑定!
wails是一个可以让你使用Go和Web技术编写桌面应用的项目 可以将它看作Go的快并且轻量级的Electron替代品。可以使用Go的功能,并结合现代化UI完成桌面应用程序的开发
515 4
|
6月前
|
JSON 中间件 Go
Go 网络编程:HTTP服务与客户端开发
Go 语言的 `net/http` 包功能强大,可快速构建高并发 HTTP 服务。本文从创建简单 HTTP 服务入手,逐步讲解请求与响应对象、URL 参数处理、自定义路由、JSON 接口、静态文件服务、中间件编写及 HTTPS 配置等内容。通过示例代码展示如何使用 `http.HandleFunc`、`http.ServeMux`、`http.Client` 等工具实现常见功能,帮助开发者掌握构建高效 Web 应用的核心技能。
378 61
|
5月前
|
监控 Linux 应用服务中间件
linux查看日志文件tail -f用法
在 Linux 中,查看和监控日志文件是系统管理员和开发者常用的操作之一。tail 命令就是用来查看文件内容的,它默认显示文件的最后部分。tail -f 是 tail 命令的一个非常有用的选项,用于实时查看和跟踪日志文件的更新,尤其是在监控运行中的服务时非常有用。
726 0
|
6月前
|
开发框架 安全 前端开发
Go Web开发框架实践:模板渲染与静态资源服务
Gin 是一个功能强大的 Go Web 框架,不仅适用于构建 API 服务,还支持 HTML 模板渲染和静态资源托管。它可以帮助开发者快速搭建中小型网站,并提供灵活的模板语法、自定义函数、静态文件映射等功能,同时兼容 Go 的 html/template 引擎,具备高效且安全的页面渲染能力。
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
3767 31
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
7月前
|
监控 容灾 算法
阿里云 SLS 多云日志接入最佳实践:链路、成本与高可用性优化
本文探讨了如何高效、经济且可靠地将海外应用与基础设施日志统一采集至阿里云日志服务(SLS),解决全球化业务扩展中的关键挑战。重点介绍了高性能日志采集Agent(iLogtail/LoongCollector)在海外场景的应用,推荐使用LoongCollector以获得更优的稳定性和网络容错能力。同时分析了多种网络接入方案,包括公网直连、全球加速优化、阿里云内网及专线/CEN/VPN接入等,并提供了成本优化策略和多目标发送配置指导,帮助企业构建稳定、低成本、高可用的全球日志系统。
825 54
|
监控 安全 Apache
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。
367 9