Golang解析命令行输出并生成报告的方法与实践

Golang解析命令行输出并生成报告的方法与实践 嗨, 距离我上次访问这个论坛或使用Go语言已经有一段时间了。我带着一个非常具体的问题回来了。在我的新工作中,有一个需求是解析和过滤命令行输出,根据数据发送电子邮件、创建Excel和HTML报告。我将在其上运行报告应用程序的服务器是Ubuntu Linux。输出本质上大多是类Unix风格的。Go语言适合这个任务吗,还是Python会更好?

4 回复

pritesh: Go语言适合吗

是的

pritesh: Python会更好吗

这取决于你的标准

更多关于Golang解析命令行输出并生成报告的方法与实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


@Dean_Davidson 太遗憾了,我只能点赞一次!!

在我看来,这个库似乎允许向现有的 Excel 文档添加工作表!!如果要写入大量数据,这非常合适!!感谢您提供这个惊人的信息!!

pritesh:

对于这个任务,Go 语言合适还是 Python 更好?

具体来说,几乎不存在绝对的“更好”选项;这只是一系列权衡。哪个生态系统的库更符合你的偏好?哪个更符合你的团队构成和未来目标?等等。任何声称一种语言比另一种“更好”的人,要么是在推销什么(通常是点击诱饵标题的广告),要么是严重被误导了。除非他们是在抨击 Java 和 FactoryBeanSimpleInitializerFactoryInterface 这种类型的类名;那是允许的。😉

话虽如此,我使用过很多 Excel 库,而 qax-os/excelize 无疑是最佳/最易用的之一。讽刺的是,我更喜欢它而不是微软自家的产品(特别是他们的开放 XML SDK;他们的 Excel 自动化虽然易用,但当然需要 Excel 本身)。因此,这将成为我在此决策过程中的一个主要因素。

Go语言非常适合这个任务,特别是在处理命令行输出和生成报告方面。以下是一个完整的示例,展示如何解析命令行输出、过滤数据,并生成HTML和Excel报告。

1. 解析命令行输出

使用os/exec执行命令并解析输出:

package main

import (
    "bufio"
    "fmt"
    "os/exec"
    "strings"
)

type Process struct {
    User    string
    PID     string
    CPU     string
    Memory  string
    Command string
}

func parsePSOutput() ([]Process, error) {
    cmd := exec.Command("ps", "aux")
    output, err := cmd.Output()
    if err != nil {
        return nil, err
    }

    var processes []Process
    scanner := bufio.NewScanner(strings.NewReader(string(output)))
    scanner.Scan() // 跳过标题行

    for scanner.Scan() {
        line := scanner.Text()
        fields := strings.Fields(line)
        if len(fields) >= 11 {
            process := Process{
                User:    fields[0],
                PID:     fields[1],
                CPU:     fields[2],
                Memory:  fields[3],
                Command: strings.Join(fields[10:], " "),
            }
            processes = append(processes, process)
        }
    }
    return processes, nil
}

2. 过滤数据

根据条件过滤进程数据:

func filterProcesses(processes []Process, minCPU float64) []Process {
    var filtered []Process
    for _, p := range processes {
        var cpu float64
        fmt.Sscanf(p.CPU, "%f", &cpu)
        if cpu >= minCPU {
            filtered = append(filtered, p)
        }
    }
    return filtered
}

3. 生成HTML报告

使用模板生成HTML报告:

import (
    "html/template"
    "os"
)

const htmlTemplate = `
<!DOCTYPE html>
<html>
<head>
    <title>进程报告</title>
    <style>
        table { border-collapse: collapse; width: 100%; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #4CAF50; color: white; }
        tr:nth-child(even) { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <h2>高CPU进程报告</h2>
    <table>
        <tr>
            <th>用户</th><th>PID</th><th>CPU%</th><th>内存%</th><th>命令</th>
        </tr>
        {{range .}}
        <tr>
            <td>{{.User}}</td>
            <td>{{.PID}}</td>
            <td>{{.CPU}}</td>
            <td>{{.Memory}}</td>
            <td>{{.Command}}</td>
        </tr>
        {{end}}
    </table>
</body>
</html>`

func generateHTMLReport(processes []Process, filename string) error {
    tmpl, err := template.New("report").Parse(htmlTemplate)
    if err != nil {
        return err
    }

    file, err := os.Create(filename)
    if err != nil {
        return err
    }
    defer file.Close()

    return tmpl.Execute(file, processes)
}

4. 生成Excel报告

使用tealeg/xlsx库创建Excel文件:

import (
    "github.com/tealeg/xlsx"
)

func generateExcelReport(processes []Process, filename string) error {
    file := xlsx.NewFile()
    sheet, err := file.AddSheet("进程报告")
    if err != nil {
        return err
    }

    // 添加标题行
    header := sheet.AddRow()
    header.AddCell().SetString("用户")
    header.AddCell().SetString("PID")
    header.AddCell().SetString("CPU%")
    header.AddCell().SetString("内存%")
    header.AddCell().SetString("命令")

    // 添加数据行
    for _, p := range processes {
        row := sheet.AddRow()
        row.AddCell().SetString(p.User)
        row.AddCell().SetString(p.PID)
        row.AddCell().SetString(p.CPU)
        row.AddCell().SetString(p.Memory)
        row.AddCell().SetString(p.Command)
    }

    return file.Save(filename)
}

5. 发送电子邮件

使用net/smtp发送报告:

import (
    "net/smtp"
)

func sendEmailReport(attachmentPath string) error {
    from := "sender@example.com"
    password := "password"
    to := []string{"recipient@example.com"}
    smtpHost := "smtp.example.com"
    smtpPort := "587"

    // 读取文件内容
    data, err := os.ReadFile(attachmentPath)
    if err != nil {
        return err
    }

    msg := []byte("Subject: 进程报告\r\n" +
        "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\r\n\r\n" +
        string(data))

    auth := smtp.PlainAuth("", from, password, smtpHost)
    return smtp.SendMail(smtpHost+":"+smtpPort, auth, from, to, msg)
}

6. 主函数

整合所有功能:

func main() {
    // 解析命令行输出
    processes, err := parsePSOutput()
    if err != nil {
        fmt.Printf("解析失败: %v\n", err)
        return
    }

    // 过滤CPU使用率大于1%的进程
    filtered := filterProcesses(processes, 1.0)

    // 生成HTML报告
    if err := generateHTMLReport(filtered, "report.html"); err != nil {
        fmt.Printf("生成HTML报告失败: %v\n", err)
    }

    // 生成Excel报告
    if err := generateExcelReport(filtered, "report.xlsx"); err != nil {
        fmt.Printf("生成Excel报告失败: %v\n", err)
    }

    // 发送电子邮件
    if err := sendEmailReport("report.html"); err != nil {
        fmt.Printf("发送邮件失败: %v\n", err)
    }

    fmt.Println("报告生成完成")
}

7. 依赖安装

安装Excel库:

go get github.com/tealeg/xlsx/v3

总结

这个示例展示了Go语言在解析命令行输出、数据处理和报告生成方面的完整能力。Go的静态编译特性使得部署到Ubuntu服务器非常方便,单个二进制文件即可运行所有功能,无需担心依赖问题。性能方面,Go在处理大量数据时比Python更有优势,特别是在并发处理场景下。

回到顶部