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

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 嵌入式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!


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
312 76
|
6月前
|
用 Zap 轻松搞定 Go 语言中的结构化日志
在现代应用程序开发中,日志记录至关重要。Go 语言中有许多日志库,而 Zap 因其高性能和灵活性脱颖而出。本文详细介绍如何在 Go 项目中使用 Zap 进行结构化日志记录,并展示如何定制日志输出,满足生产环境需求。通过基础示例、SugaredLogger 的便捷使用以及自定义日志配置,帮助你在实际开发中高效管理日志。
154 1
PHP 日志系统的最佳搭档:一个 Go 写的远程日志收集服务
为了不再 SSH 上去翻日志,我写了个 Go 小脚本,用来接收远程日志。PHP 负责记录日志,Go 负责存储和展示,按天存储、支持 API 访问、可远程管理,终于能第一时间知道项目炸了。
47 10
Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统
使用上述U-Boot命令配置并启动嵌入式设备。如果配置正确,设备将通过TFTP加载内核和设备树,并通过NFS挂载根文件系统。
231 15
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
198 13
纯Go语言开发人脸检测、瞳孔/眼睛定位与面部特征检测插件-助力GoFly快速开发框架
开发纯go插件的原因是因为目前 Go 生态系统中几乎所有现有的人脸检测解决方案都是纯粹绑定到一些 C/C++ 库,如 OpenCV 或 dlib,但通过 cgo 调用 C 程序会引入巨大的延迟,并在性能方面产生显著的权衡。此外,在许多情况下,在各种平台上安装 OpenCV 是很麻烦的。使用纯Go开发的插件不仅在开发时方便,在项目部署和项目维护也能省很多时间精力。
115 5
Go语言开发
【10月更文挑战第26天】Go语言开发
72 3
Linux 系统中的代码类型或脚本类型内容
在 Linux 系统中,代码类型多样,包括 Shell 脚本、配置文件、网络配置、命令行工具和 Cron 定时任务。这些代码类型广泛应用于系统管理、自动化操作、网络配置和定期任务,掌握它们能显著提高系统管理和开发的效率。
|
6月前
|
Go语言的开发
【10月更文挑战第25天】Go语言的开发
65 3
|
7月前
|
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
220 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等