aboutsummaryrefslogtreecommitdiffstats
path: root/filter/filter.go
blob: 6391afc973318a8b8d2a970bd08f9d60d289bc1b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"os"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

const (
	oldDBName      = "test"
	oldPidColName  = "pids"
	oldFdColName   = "fds"
	oldFileColName = "files"

	newDBName      = "cooked"
	newPidColName  = "tgids"
	newFileColName = "files"
)

// 进程树信息
var findTgid map[int]int
var helloTree map[int]*tgidNode

// 文件信息
var files []File

func main() {
	// 连接到MongoDB
	client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI("mongodb://192.168.192.136:27017"))
	if err != nil {
		log.Fatal(err)
	}
	defer client.Disconnect(context.TODO())

	oldDB := client.Database(oldDBName)

	/*
	 * Step 1: 进程数据处理
	 */
	oldPidCol := oldDB.Collection(oldPidColName)

	// 数据提取
	var rawPidData []Process
	cursor, err := oldPidCol.Find(context.Background(), bson.M{})
	if err != nil {
		fmt.Fprintf(os.Stderr, "Err: %v\n", err)
		return
	}
	err = cursor.All(context.Background(), &rawPidData)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Err All: %v\n", err)
		return
	}
	cursor.Close(context.Background())

	filtPids(&rawPidData)

	/*
	 * Step 2: 文件数据处理
	 * - 将已经关闭的和未关闭的同等看待
	 * - 未关闭的将关闭时间修改为对应进程退出时间
	 * - 值得注意的是,同一进程各线程共享文件描述符……需要处理吗?
	 */
	// 提取files和fds里的数据
	// TODO:是否可以只筛选被写过的记录?
	var rawFileData []File
	oldFileCol := oldDB.Collection(oldFileColName)
	cursor, err = oldFileCol.Find(context.Background(), bson.M{})
	if err != nil {
		fmt.Fprintf(os.Stderr, "Err: %v\n", err)
		return
	}
	err = cursor.All(context.Background(), &rawFileData)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Err All: %v\n", err)
		return
	}
	cursor.Close(context.Background())

	var rawFdData []File
	oldFdCol := oldDB.Collection(oldFdColName)
	cursor, err = oldFdCol.Find(context.Background(), bson.M{})
	if err != nil {
		fmt.Fprintf(os.Stderr, "Err: %v\n", err)
		return
	}
	err = cursor.All(context.Background(), &rawFdData)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Err All: %v\n", err)
		return
	}
	cursor.Close(context.Background())

	// 合并,处理
	rawFileData = append(rawFileData, rawFdData...)
	filtFiles(&rawFileData)

	// 扔回数据库
	newDB := client.Database(newDBName)
	newDB.Drop(context.Background())
	newPidCol := newDB.Collection(newPidColName)
	for _, pTgidNode := range helloTree {
		newPidCol.InsertOne(context.Background(), *pTgidNode)
	}

	newFileCol := newDB.Collection(newFileColName)
	for _, file := range files {
		newFileCol.InsertOne(context.Background(), file)
	}

	/* Step 3: 输出到文件
	 * - 所有内容输出到logs目录,所有文本存在则覆盖,不存在则创建
	 * - 进程树输出到logs/tree.log
	 * - 每个进程以json格式输出到logs/pids.log
	 * - 文件信息输出到logs/files.log
	 */
	stat, err := os.Stat("logs")
	if err != nil || !stat.IsDir() {
		os.Mkdir("logs", 0755)
	}

	// 进程树
	treeFile, err := os.OpenFile("logs/tree.log", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Err: %v\n", err)
		return
	}
	defer treeFile.Close()
	pidFile, err := os.OpenFile("logs/pid.log", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Err: %v\n", err)
		return
	}
	defer pidFile.Close()
	// 从starTgid开始,按照树的形状输出
	drawTree(treeFile, pidFile, helloTree[starTgid], "", true)

	// 文件信息,json格式
	fileFile, err := os.OpenFile("logs/files.log", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Err: %v\n", err)
		return
	}
	defer fileFile.Close()
	for _, file := range files {
		jsonData, err := json.MarshalIndent(file, "", "    ")
		if err != nil {
			fmt.Fprintf(os.Stderr, "Err: %v\n", err)
			return
		}
		fileFile.Write(jsonData)
		fileFile.WriteString("\n\n")
	}
}