diff options
Diffstat (limited to 'src/deal.go')
-rw-r--r-- | src/deal.go | 173 |
1 files changed, 102 insertions, 71 deletions
diff --git a/src/deal.go b/src/deal.go index 118d914..783dab8 100644 --- a/src/deal.go +++ b/src/deal.go | |||
@@ -1,51 +1,48 @@ | |||
1 | package main | 1 | package main |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "context" | ||
5 | "fmt" | 4 | "fmt" |
5 | "sync" | ||
6 | "time" | 6 | "time" |
7 | 7 | ||
8 | "go.mongodb.org/mongo-driver/bson" | 8 | "go.mongodb.org/mongo-driver/bson" |
9 | "go.mongodb.org/mongo-driver/mongo" | ||
10 | "go.mongodb.org/mongo-driver/mongo/options" | ||
11 | ) | 9 | ) |
12 | 10 | ||
13 | const ( | 11 | const ( |
14 | dbName string = "test" | 12 | dbName string = "test" |
15 | colName string = "pids" | 13 | pidColName string = "pids" |
16 | ) | 14 | ) |
17 | 15 | ||
16 | var mongoMutex sync.Mutex | ||
17 | var pidCol mongoClient | ||
18 | |||
18 | func deal() { | 19 | func deal() { |
19 | defer wg.Done() | 20 | defer wg.Done() |
20 | var cooked Event | 21 | var cooked Event |
21 | var ok bool | 22 | var ok bool |
22 | 23 | ||
23 | var err error | 24 | var err error |
24 | var mongo *mongo.Client | ||
25 | var res []bson.M | 25 | var res []bson.M |
26 | 26 | ||
27 | mongo, err = connect() | 27 | if err = pidCol.Connect(dbName, pidColName); err != nil { |
28 | if err != nil { | 28 | fmt.Printf("Error connecting the mongodb: %v\n", err) |
29 | fmt.Printf("Err connecting the mongodb: %v\n", err) | ||
30 | } | 29 | } |
31 | pidCol := mongo.Database(dbName).Collection(colName) | 30 | if err = pidCol.Drop(); err != nil { |
32 | 31 | fmt.Printf("Error drop the mongodb: %v\n", err) | |
33 | err = pidCol.Drop(context.Background()) | ||
34 | if err != nil { | ||
35 | fmt.Printf("Err drop: %v\n", err) | ||
36 | } | 32 | } |
37 | 33 | ||
38 | _, err = pidCol.InsertOne(context.Background(), bson.M{ | 34 | err = pidCol.InsertOne(bson.M{ |
39 | "ppid": 1, | 35 | "ppid": 1, |
40 | "pid": containerdPid, | 36 | "pid": containerdPid, |
41 | "cwd": "/", | 37 | "cwd": "/", |
38 | "children": bson.M{}, | ||
42 | }) | 39 | }) |
43 | if err != nil { | 40 | if err != nil { |
44 | fmt.Printf("Err containerd: %v", err) | 41 | fmt.Printf("Err containerd: %v", err) |
45 | return | 42 | return |
46 | } | 43 | } |
47 | |||
48 | fmt.Printf("Containerd: %d\n", containerdPid) | 44 | fmt.Printf("Containerd: %d\n", containerdPid) |
45 | defer pidCol.Disconnect() | ||
49 | 46 | ||
50 | for { | 47 | for { |
51 | cooked, ok = <-cookedChan | 48 | cooked, ok = <-cookedChan |
@@ -54,81 +51,115 @@ func deal() { | |||
54 | } | 51 | } |
55 | 52 | ||
56 | switch syscallTable[cooked.syscall] { | 53 | switch syscallTable[cooked.syscall] { |
57 | case "fork", "vfork", "clone": | 54 | case "clone": |
58 | // 有无父进程在观察中 | 55 | // 有无父进程在观察中 |
59 | res, err = findDocuments(mongo, "test", "pids", bson.M{"pid": cooked.ppid}) | 56 | res, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid}) |
60 | if err != nil || len(res) != 1 { | 57 | if err != nil || len(res) != 1 { |
61 | break | 58 | break |
62 | } | 59 | } |
63 | 60 | ||
64 | // 自身是否已经记录 | 61 | // 自身是否已经记录 |
65 | res, err = findDocuments(mongo, "test", "pids", bson.M{"pid": cooked.pid}) | 62 | res, err = pidCol.Finddoc(bson.M{"pid": cooked.pid}) |
66 | if err != nil { | 63 | if err != nil { |
67 | fmt.Printf("Err finding: %v\n", err) | 64 | fmt.Printf("Err finding: %v\n", err) |
68 | break | 65 | break |
69 | } else if len(res) != 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 | } | 66 | } |
78 | _, err := pidCol.InsertOne(context.Background(), bson.M{ | 67 | mongoMutex.Lock() |
79 | "timestamp": cooked.timestamp, | 68 | if len(res) != 0 { |
80 | "ppid": cooked.ppid, | 69 | // 进程原本就存在,换言之别的消息先到了 |
81 | "pid": cooked.pid, | 70 | // 所有先行抵达的消息必须保留execve/children字段 |
82 | "cwd": cooked.cwd, | 71 | // 此处不再更新 |
83 | "args": doc, | 72 | // 以防把原有信息更没了 |
84 | "children": []bson.M{}, | 73 | pidCol.UpdateOne(bson.M{"pid": cooked.pid}, bson.M{ |
85 | }) | 74 | "start_timestamp": cooked.timestamp, |
86 | if err != nil { | 75 | "ppid": cooked.ppid, |
87 | fmt.Printf("Err insert: %v\n", err) | 76 | "pid": cooked.pid, |
77 | "cwd": cooked.cwd, | ||
78 | // "execve": []bson.M{}, | ||
79 | "args": cooked.argv, | ||
80 | // "children": []bson.M{}, | ||
81 | }) | ||
82 | } else { | ||
83 | // 这进程本是新修的 | ||
84 | pidCol.InsertOne(bson.M{ | ||
85 | "start_timestamp": cooked.timestamp, | ||
86 | "ppid": cooked.ppid, | ||
87 | "pid": cooked.pid, | ||
88 | "cwd": cooked.cwd, | ||
89 | "execve": []bson.M{}, | ||
90 | "args": cooked.argv, | ||
91 | "children": []bson.M{}, | ||
92 | }) | ||
88 | } | 93 | } |
89 | 94 | ||
90 | _, err = pidCol.UpdateOne(context.Background(), bson.M{"pid": cooked.pid}, bson.M{ | 95 | pidCol.UpdateOne(bson.M{"pid": cooked.ppid}, bson.M{ |
91 | "$push": bson.M{ | 96 | "$push": bson.M{ |
92 | "children": cooked.pid, | 97 | "children": cooked.pid, |
93 | }, | 98 | }, |
94 | }) | 99 | }) |
100 | mongoMutex.Unlock() | ||
101 | case "execve": | ||
102 | // 父进程在不在?不在扔 | ||
103 | res, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid}) | ||
104 | if err != nil || len(res) != 1 { | ||
105 | break | ||
106 | } | ||
107 | |||
108 | // 首先检查进程是否存在,如不存在则为之创建 | ||
109 | res, err = pidCol.Finddoc(bson.M{"pid": cooked.pid}) | ||
95 | if err != nil { | 110 | if err != nil { |
96 | fmt.Printf("Err insert: %v\n", err) | 111 | break |
112 | } | ||
113 | mongoMutex.Lock() | ||
114 | if len(res) == 1 { | ||
115 | // 自身已在,直接记录 | ||
116 | pidCol.UpdateOne(bson.M{"pid": cooked.pid}, bson.M{ | ||
117 | "$push": bson.M{ | ||
118 | "execve": bson.M{ | ||
119 | "timestamp": cooked.timestamp, | ||
120 | "args": cooked.argv, | ||
121 | }, | ||
122 | }, | ||
123 | }) | ||
124 | } else { | ||
125 | // 先fork抵达,插入 | ||
126 | pidCol.InsertOne(bson.M{ | ||
127 | "children": []bson.M{}, | ||
128 | "execve": []bson.M{ | ||
129 | { | ||
130 | "timestamp": cooked.timestamp, | ||
131 | "execve": cooked.argv, | ||
132 | }, | ||
133 | }, | ||
134 | }) | ||
97 | } | 135 | } |
136 | mongoMutex.Unlock() | ||
98 | case "exit", "exit_group": | 137 | case "exit", "exit_group": |
99 | // TODO: 记得补全退出逻辑 | 138 | go deletePid(cooked) |
100 | // 上哪找exit code呢? | ||
101 | } | 139 | } |
102 | } | 140 | } |
103 | } | 141 | } |
104 | 142 | ||
105 | func connect() (*mongo.Client, error) { | 143 | func deletePid(cooked Event) { |
106 | client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017")) | 144 | time.Sleep(1 * time.Second) |
107 | 145 | mongoMutex.Lock() | |
108 | if err != nil { | 146 | // 先从老爹那里销户 |
109 | return nil, err | 147 | pidCol.UpdateOne(bson.M{"pid": cooked.ppid}, bson.M{ |
110 | } | 148 | "$pull": bson.M{ |
111 | 149 | "children": cooked.pid, | |
112 | ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) | 150 | }, |
113 | err = client.Connect(ctx) | 151 | }) |
114 | |||
115 | if err != nil { | ||
116 | return nil, err | ||
117 | } | ||
118 | |||
119 | return client, nil | ||
120 | } | ||
121 | |||
122 | func findDocuments(client *mongo.Client, dbName, colName string, filter bson.M) ([]bson.M, error) { | ||
123 | collection := client.Database(dbName).Collection(colName) | ||
124 | |||
125 | cur, err := collection.Find(context.Background(), filter) | ||
126 | if err != nil { | ||
127 | return nil, err | ||
128 | } | ||
129 | 152 | ||
130 | var results []bson.M | 153 | // 孩子们需要收容 |
131 | err = cur.All(context.Background(), &results) | 154 | // 不必到children里一个个找,直接看ppid即可 |
155 | pidCol.UpdateMany(bson.M{"ppid": cooked.pid}, bson.M{"ppid": 1}) | ||
132 | 156 | ||
133 | return results, err | 157 | // 可以去死了 |
158 | pidCol.UpdateOne(bson.M{"pid": cooked.pid}, bson.M{ | ||
159 | "$set": bson.M{ | ||
160 | "exit_timestamp": cooked.timestamp, | ||
161 | "exit_code": cooked.exit_code, | ||
162 | }, | ||
163 | }) | ||
164 | mongoMutex.Unlock() | ||
134 | } | 165 | } |