diff options
author | We-unite <3205135446@qq.com> | 2024-07-22 11:41:59 +0800 |
---|---|---|
committer | We-unite <3205135446@qq.com> | 2024-07-22 19:36:34 +0800 |
commit | cf5618ff2e2a183c5bdf6444787dccdcbf26ce76 (patch) | |
tree | 6cc173b9bffe2c1414887a338b6dc2bdbd594fd1 /src/deal.go | |
parent | 7cf8e470471d30fc821a8be350dcb97dc64e5add (diff) | |
download | godo-cf5618ff2e2a183c5bdf6444787dccdcbf26ce76.tar.gz godo-cf5618ff2e2a183c5bdf6444787dccdcbf26ce76.zip |
Use mongodb, insert process info into it
I failed to print the process tree out. While I'm printing the tree,
the tree itself gets changed, maybe deleted. What's more, the output
show that there are 4 lines with the same ppid and pid, how an absurd
result! It may be caused by multi-thread. So, use database instead.
Mongodb uses bson(binary json) to store data but not relational
database like mysql, which means it's more easy to use.(?)
Beside inserting, I've also solved a question that "fork" is called
once but returns twice. For instance, pid 1 forked pid 2, in the
audit log it's not an event "syscall=clone,ppid=1,pid=2", but actually
two events "syscall=clone,exit=0,ppid=0,pid=1" and "syscall=clone,exit=
2,ppid=0,pid=1", which is just what we see in sys_fork in kernel source.
To deal with this, when syscall is clone and exit is 0 we just drop it.
Left question: To find out the exit code when a process exit/exit_group,
and finish the code to record it in the database.
Diffstat (limited to 'src/deal.go')
-rw-r--r-- | src/deal.go | 165 |
1 files changed, 101 insertions, 64 deletions
diff --git a/src/deal.go b/src/deal.go index fd9f788..118d914 100644 --- a/src/deal.go +++ b/src/deal.go | |||
@@ -1,97 +1,134 @@ | |||
1 | package main | 1 | package main |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "context" | ||
4 | "fmt" | 5 | "fmt" |
5 | "time" | 6 | "time" |
7 | |||
8 | "go.mongodb.org/mongo-driver/bson" | ||
9 | "go.mongodb.org/mongo-driver/mongo" | ||
10 | "go.mongodb.org/mongo-driver/mongo/options" | ||
11 | ) | ||
12 | |||
13 | const ( | ||
14 | dbName string = "test" | ||
15 | colName string = "pids" | ||
6 | ) | 16 | ) |
7 | 17 | ||
8 | func deal() { | 18 | func deal() { |
9 | defer wg.Done() | 19 | defer wg.Done() |
10 | var cooked Event | 20 | var cooked Event |
11 | var ok bool | 21 | var ok bool |
22 | |||
23 | var err error | ||
24 | var mongo *mongo.Client | ||
25 | var res []bson.M | ||
26 | |||
27 | mongo, err = connect() | ||
28 | if err != nil { | ||
29 | fmt.Printf("Err connecting the mongodb: %v\n", err) | ||
30 | } | ||
31 | pidCol := mongo.Database(dbName).Collection(colName) | ||
32 | |||
33 | err = pidCol.Drop(context.Background()) | ||
34 | if err != nil { | ||
35 | fmt.Printf("Err drop: %v\n", err) | ||
36 | } | ||
37 | |||
38 | _, err = pidCol.InsertOne(context.Background(), bson.M{ | ||
39 | "ppid": 1, | ||
40 | "pid": containerdPid, | ||
41 | "cwd": "/", | ||
42 | }) | ||
43 | if err != nil { | ||
44 | fmt.Printf("Err containerd: %v", err) | ||
45 | return | ||
46 | } | ||
47 | |||
48 | fmt.Printf("Containerd: %d\n", containerdPid) | ||
49 | |||
12 | for { | 50 | for { |
13 | cooked, ok = <-cookedChan | 51 | cooked, ok = <-cookedChan |
14 | if !ok { | 52 | if !ok { |
15 | break | 53 | break |
16 | } | 54 | } |
17 | // type Event struct { | 55 | |
18 | // timestamp time.Time | ||
19 | // pid, ppid int | ||
20 | // syscall int | ||
21 | // argc int | ||
22 | // args []string | ||
23 | // cwd string | ||
24 | // } | ||
25 | // type process struct { | ||
26 | // timestamp time.Time | ||
27 | // pid, ppid int | ||
28 | // argv []string | ||
29 | // cwd string | ||
30 | // rootfs string | ||
31 | // children []int | ||
32 | // } | ||
33 | switch syscallTable[cooked.syscall] { | 56 | switch syscallTable[cooked.syscall] { |
34 | case "fork", "vfork", "clone": | 57 | case "fork", "vfork", "clone": |
35 | ppid := cooked.ppid | 58 | // 有无父进程在观察中 |
36 | pid := cooked.pid | 59 | res, err = findDocuments(mongo, "test", "pids", bson.M{"pid": cooked.ppid}) |
37 | parent, ok := pids.Load(ppid) | 60 | if err != nil || len(res) != 1 { |
38 | if !ok { | ||
39 | break | 61 | break |
40 | } | 62 | } |
41 | parent.(*process).children = append(parent.(*process).children, pid) | 63 | |
42 | pids.Store(pid, &process{ | 64 | // 自身是否已经记录 |
43 | timestamp: cooked.timestamp, | 65 | res, err = findDocuments(mongo, "test", "pids", bson.M{"pid": cooked.pid}) |
44 | pid: cooked.pid, | 66 | if err != nil { |
45 | ppid: cooked.ppid, | 67 | fmt.Printf("Err finding: %v\n", err) |
46 | argv: cooked.argv, | 68 | break |
47 | cwd: cooked.cwd, | 69 | } else if len(res) != 0 { |
48 | children: make([]int, 0), | 70 | fmt.Printf("Err inserting pid %v: already in db: %v\n", cooked.pid, res) |
71 | break | ||
72 | } | ||
73 | |||
74 | doc := []bson.A{} | ||
75 | for _, str := range cooked.argv { | ||
76 | doc = append(doc, bson.A{str}) | ||
77 | } | ||
78 | _, err := pidCol.InsertOne(context.Background(), bson.M{ | ||
79 | "timestamp": cooked.timestamp, | ||
80 | "ppid": cooked.ppid, | ||
81 | "pid": cooked.pid, | ||
82 | "cwd": cooked.cwd, | ||
83 | "args": doc, | ||
84 | "children": []bson.M{}, | ||
49 | }) | 85 | }) |
50 | fmt.Printf("%v syscall=%d, ppid=%d, pid=%d, cwd=\"%s\", argc=%d, ", cooked.timestamp, cooked.syscall, cooked.ppid, cooked.pid, cooked.cwd, cooked.argc) | 86 | if err != nil { |
51 | for i := 0; i < cooked.argc; i++ { | 87 | fmt.Printf("Err insert: %v\n", err) |
52 | fmt.Printf("arg[%d]=\"%s\", ", i, cooked.argv[i]) | ||
53 | } | 88 | } |
54 | fmt.Printf("\n") | 89 | |
55 | case "exit", "exit_group": | 90 | _, err = pidCol.UpdateOne(context.Background(), bson.M{"pid": cooked.pid}, bson.M{ |
56 | _, ok := pids.Load(cooked.pid) | 91 | "$push": bson.M{ |
57 | if !ok { | 92 | "children": cooked.pid, |
58 | break | 93 | }, |
94 | }) | ||
95 | if err != nil { | ||
96 | fmt.Printf("Err insert: %v\n", err) | ||
59 | } | 97 | } |
60 | go deletePid(cooked) | 98 | case "exit", "exit_group": |
99 | // TODO: 记得补全退出逻辑 | ||
100 | // 上哪找exit code呢? | ||
61 | } | 101 | } |
62 | } | 102 | } |
63 | } | 103 | } |
64 | 104 | ||
65 | func deletePid(cooked Event) { | 105 | func connect() (*mongo.Client, error) { |
66 | time.Sleep(1 * time.Second) | 106 | client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017")) |
67 | Process, ok := pids.Load(cooked.pid) | 107 | |
68 | if !ok { | 108 | if err != nil { |
69 | return | 109 | return nil, err |
70 | } | 110 | } |
71 | pProcess := Process.(*process) | 111 | |
72 | 112 | ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) | |
73 | // 先从爹那里注销户籍 | 113 | err = client.Connect(ctx) |
74 | parent, ok := pids.Load(pProcess.ppid) | 114 | |
75 | if ok { | 115 | if err != nil { |
76 | pParent := parent.(*process) | 116 | return nil, err |
77 | for i, child := range pParent.children { | ||
78 | if child == pProcess.pid { | ||
79 | pParent.children = append(pParent.children[:i], pParent.children[i+1:]...) | ||
80 | break | ||
81 | } | ||
82 | } | ||
83 | } | 117 | } |
84 | 118 | ||
85 | // 子进程需要收容 | 119 | return client, nil |
86 | for i := 0; i < len(pProcess.children); i++ { | 120 | } |
87 | child, ok := pids.Load(pProcess.children[i]) | 121 | |
88 | if ok { | 122 | func findDocuments(client *mongo.Client, dbName, colName string, filter bson.M) ([]bson.M, error) { |
89 | child.(*process).ppid = 1 | 123 | collection := client.Database(dbName).Collection(colName) |
90 | } | 124 | |
125 | cur, err := collection.Find(context.Background(), filter) | ||
126 | if err != nil { | ||
127 | return nil, err | ||
91 | } | 128 | } |
92 | 129 | ||
93 | // 可以去死了 | 130 | var results []bson.M |
94 | pids.Delete(cooked.pid) | 131 | err = cur.All(context.Background(), &results) |
95 | _, ok = pids.Load(cooked.pid) | 132 | |
96 | fmt.Printf("%v Goodbye, %d! ok = %v\n", time.Now(), cooked.pid, ok) | 133 | return results, err |
97 | } | 134 | } |