rewind-timeline 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rewind_timeline-0.1.0/LICENSE +21 -0
- rewind_timeline-0.1.0/PKG-INFO +274 -0
- rewind_timeline-0.1.0/README.md +261 -0
- rewind_timeline-0.1.0/collectors/__init__.py +0 -0
- rewind_timeline-0.1.0/collectors/collect.py +52 -0
- rewind_timeline-0.1.0/collectors/files.py +104 -0
- rewind_timeline-0.1.0/collectors/packages.py +62 -0
- rewind_timeline-0.1.0/collectors/performance.py +50 -0
- rewind_timeline-0.1.0/collectors/services.py +56 -0
- rewind_timeline-0.1.0/collectors/shell.py +55 -0
- rewind_timeline-0.1.0/commands/__init__.py +0 -0
- rewind_timeline-0.1.0/commands/search.py +28 -0
- rewind_timeline-0.1.0/commands/stats.py +54 -0
- rewind_timeline-0.1.0/commands/today.py +31 -0
- rewind_timeline-0.1.0/commands/yesterday.py +35 -0
- rewind_timeline-0.1.0/database.py +104 -0
- rewind_timeline-0.1.0/pyproject.toml +14 -0
- rewind_timeline-0.1.0/rewind.py +80 -0
- rewind_timeline-0.1.0/rewind_timeline.egg-info/PKG-INFO +274 -0
- rewind_timeline-0.1.0/rewind_timeline.egg-info/SOURCES.txt +23 -0
- rewind_timeline-0.1.0/rewind_timeline.egg-info/dependency_links.txt +1 -0
- rewind_timeline-0.1.0/rewind_timeline.egg-info/top_level.txt +4 -0
- rewind_timeline-0.1.0/setup.cfg +23 -0
- rewind_timeline-0.1.0/setup.py +8 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DarkGlitch
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rewind-timeline
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Linux timeline collector and monitoring tool
|
|
5
|
+
Home-page: https://github.com/LaVenganzaDelLadron/rewind.git
|
|
6
|
+
Author: DarkGlitch
|
|
7
|
+
Author-email: darkglitch5417@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
# Rewind
|
|
15
|
+
|
|
16
|
+
**Rewind** is a Linux Time Machine that records important system events and allows users to revisit what happened on their machine.
|
|
17
|
+
|
|
18
|
+
It helps answer questions such as:
|
|
19
|
+
|
|
20
|
+
* What changed yesterday?
|
|
21
|
+
* Why did my system become slow?
|
|
22
|
+
* Which package was installed?
|
|
23
|
+
* Which service stopped?
|
|
24
|
+
* What commands did I run?
|
|
25
|
+
* Which files were modified?
|
|
26
|
+
|
|
27
|
+
Rewind stores these events locally in a SQLite database and provides a simple command-line interface for exploring the system timeline.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
* Package monitoring (Pacman support)
|
|
34
|
+
* Service monitoring
|
|
35
|
+
* Performance monitoring
|
|
36
|
+
* Shell history tracking
|
|
37
|
+
* File change monitoring
|
|
38
|
+
* Timeline search
|
|
39
|
+
* Daily activity reports
|
|
40
|
+
* System statistics
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Project Structure
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
rewind/
|
|
48
|
+
├── collect.py
|
|
49
|
+
├── rewind.py
|
|
50
|
+
├── database.py
|
|
51
|
+
│
|
|
52
|
+
├── collectors/
|
|
53
|
+
│ ├── files.py
|
|
54
|
+
│ ├── packages.py
|
|
55
|
+
│ ├── performance.py
|
|
56
|
+
│ ├── services.py
|
|
57
|
+
│ └── shell.py
|
|
58
|
+
│
|
|
59
|
+
├── commands/
|
|
60
|
+
│ ├── search.py
|
|
61
|
+
│ ├── stats.py
|
|
62
|
+
│ ├── today.py
|
|
63
|
+
│ └── yesterday.py
|
|
64
|
+
│
|
|
65
|
+
└── rewind.db
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Requirements
|
|
71
|
+
|
|
72
|
+
* Python 3.10+
|
|
73
|
+
* Linux
|
|
74
|
+
* systemd
|
|
75
|
+
* SQLite
|
|
76
|
+
|
|
77
|
+
Install dependencies:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install psutil watchdog
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Running the Collector
|
|
86
|
+
|
|
87
|
+
The collector continuously monitors the system and stores events.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
python collect.py
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The collector records:
|
|
94
|
+
|
|
95
|
+
* package changes
|
|
96
|
+
* service state changes
|
|
97
|
+
* performance alerts
|
|
98
|
+
* shell history
|
|
99
|
+
* file modifications
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Commands
|
|
104
|
+
|
|
105
|
+
### View today's events
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
python rewind.py today
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### View yesterday's events
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
python rewind.py yesterday
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Search the timeline
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
python rewind.py search nginx
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### View statistics
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
python rewind.py stats
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Show help
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
python rewind.py help
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Example
|
|
138
|
+
|
|
139
|
+
```text
|
|
140
|
+
$ python rewind.py today
|
|
141
|
+
|
|
142
|
+
Rewind - 2026-06-27
|
|
143
|
+
|
|
144
|
+
[08:32:10] [PACKAGE] Installed nginx
|
|
145
|
+
[09:15:22] [FILE] Modified /etc/ssh/sshd_config
|
|
146
|
+
[11:10:33] [PERFORMANCE] CPU usage reached 95%
|
|
147
|
+
[13:00:17] [SERVICE] nginx.service restarted
|
|
148
|
+
[13:01:55] [SHELL] sudo systemctl restart nginx
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Database
|
|
154
|
+
|
|
155
|
+
Rewind stores events inside a local SQLite database.
|
|
156
|
+
|
|
157
|
+
Location:
|
|
158
|
+
|
|
159
|
+
```text
|
|
160
|
+
~/.rewind.db
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Schema:
|
|
164
|
+
|
|
165
|
+
```sql
|
|
166
|
+
CREATE TABLE events (
|
|
167
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
168
|
+
timestamp TEXT NOT NULL,
|
|
169
|
+
category TEXT NOT NULL,
|
|
170
|
+
title TEXT NOT NULL,
|
|
171
|
+
details TEXT
|
|
172
|
+
);
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Current Collectors
|
|
178
|
+
|
|
179
|
+
### Package Collector
|
|
180
|
+
|
|
181
|
+
Parses:
|
|
182
|
+
|
|
183
|
+
```text
|
|
184
|
+
/var/log/pacman.log
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Tracks:
|
|
188
|
+
|
|
189
|
+
* installed packages
|
|
190
|
+
* removed packages
|
|
191
|
+
* upgraded packages
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
### Service Collector
|
|
196
|
+
|
|
197
|
+
Uses:
|
|
198
|
+
|
|
199
|
+
```text
|
|
200
|
+
systemctl
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Tracks:
|
|
204
|
+
|
|
205
|
+
* started services
|
|
206
|
+
* stopped services
|
|
207
|
+
* restarted services
|
|
208
|
+
* failed services
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### Performance Collector
|
|
213
|
+
|
|
214
|
+
Monitors:
|
|
215
|
+
|
|
216
|
+
* CPU usage
|
|
217
|
+
* memory usage
|
|
218
|
+
* disk usage
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
### Shell Collector
|
|
223
|
+
|
|
224
|
+
Reads:
|
|
225
|
+
|
|
226
|
+
```text
|
|
227
|
+
~/.bash_history
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Tracks executed commands.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
### File Collector
|
|
235
|
+
|
|
236
|
+
Uses:
|
|
237
|
+
|
|
238
|
+
```text
|
|
239
|
+
watchdog
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Tracks:
|
|
243
|
+
|
|
244
|
+
* created files
|
|
245
|
+
* modified files
|
|
246
|
+
* deleted files
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Roadmap
|
|
251
|
+
|
|
252
|
+
* systemd service support
|
|
253
|
+
* daemon mode
|
|
254
|
+
* multi-distribution package support
|
|
255
|
+
* export reports
|
|
256
|
+
* weekly summaries
|
|
257
|
+
* interactive TUI
|
|
258
|
+
* notifications
|
|
259
|
+
* command learning mode
|
|
260
|
+
* performance history graphs
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## License
|
|
265
|
+
|
|
266
|
+
MIT License
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Author
|
|
271
|
+
|
|
272
|
+
Created by DarkGlitch.
|
|
273
|
+
|
|
274
|
+
Rewind aims to become a personal timeline for Linux systems.
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# Rewind
|
|
2
|
+
|
|
3
|
+
**Rewind** is a Linux Time Machine that records important system events and allows users to revisit what happened on their machine.
|
|
4
|
+
|
|
5
|
+
It helps answer questions such as:
|
|
6
|
+
|
|
7
|
+
* What changed yesterday?
|
|
8
|
+
* Why did my system become slow?
|
|
9
|
+
* Which package was installed?
|
|
10
|
+
* Which service stopped?
|
|
11
|
+
* What commands did I run?
|
|
12
|
+
* Which files were modified?
|
|
13
|
+
|
|
14
|
+
Rewind stores these events locally in a SQLite database and provides a simple command-line interface for exploring the system timeline.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
* Package monitoring (Pacman support)
|
|
21
|
+
* Service monitoring
|
|
22
|
+
* Performance monitoring
|
|
23
|
+
* Shell history tracking
|
|
24
|
+
* File change monitoring
|
|
25
|
+
* Timeline search
|
|
26
|
+
* Daily activity reports
|
|
27
|
+
* System statistics
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Project Structure
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
rewind/
|
|
35
|
+
├── collect.py
|
|
36
|
+
├── rewind.py
|
|
37
|
+
├── database.py
|
|
38
|
+
│
|
|
39
|
+
├── collectors/
|
|
40
|
+
│ ├── files.py
|
|
41
|
+
│ ├── packages.py
|
|
42
|
+
│ ├── performance.py
|
|
43
|
+
│ ├── services.py
|
|
44
|
+
│ └── shell.py
|
|
45
|
+
│
|
|
46
|
+
├── commands/
|
|
47
|
+
│ ├── search.py
|
|
48
|
+
│ ├── stats.py
|
|
49
|
+
│ ├── today.py
|
|
50
|
+
│ └── yesterday.py
|
|
51
|
+
│
|
|
52
|
+
└── rewind.db
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Requirements
|
|
58
|
+
|
|
59
|
+
* Python 3.10+
|
|
60
|
+
* Linux
|
|
61
|
+
* systemd
|
|
62
|
+
* SQLite
|
|
63
|
+
|
|
64
|
+
Install dependencies:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pip install psutil watchdog
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Running the Collector
|
|
73
|
+
|
|
74
|
+
The collector continuously monitors the system and stores events.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
python collect.py
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The collector records:
|
|
81
|
+
|
|
82
|
+
* package changes
|
|
83
|
+
* service state changes
|
|
84
|
+
* performance alerts
|
|
85
|
+
* shell history
|
|
86
|
+
* file modifications
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Commands
|
|
91
|
+
|
|
92
|
+
### View today's events
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
python rewind.py today
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### View yesterday's events
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
python rewind.py yesterday
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Search the timeline
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
python rewind.py search nginx
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### View statistics
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
python rewind.py stats
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Show help
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
python rewind.py help
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Example
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
$ python rewind.py today
|
|
128
|
+
|
|
129
|
+
Rewind - 2026-06-27
|
|
130
|
+
|
|
131
|
+
[08:32:10] [PACKAGE] Installed nginx
|
|
132
|
+
[09:15:22] [FILE] Modified /etc/ssh/sshd_config
|
|
133
|
+
[11:10:33] [PERFORMANCE] CPU usage reached 95%
|
|
134
|
+
[13:00:17] [SERVICE] nginx.service restarted
|
|
135
|
+
[13:01:55] [SHELL] sudo systemctl restart nginx
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Database
|
|
141
|
+
|
|
142
|
+
Rewind stores events inside a local SQLite database.
|
|
143
|
+
|
|
144
|
+
Location:
|
|
145
|
+
|
|
146
|
+
```text
|
|
147
|
+
~/.rewind.db
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Schema:
|
|
151
|
+
|
|
152
|
+
```sql
|
|
153
|
+
CREATE TABLE events (
|
|
154
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
155
|
+
timestamp TEXT NOT NULL,
|
|
156
|
+
category TEXT NOT NULL,
|
|
157
|
+
title TEXT NOT NULL,
|
|
158
|
+
details TEXT
|
|
159
|
+
);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Current Collectors
|
|
165
|
+
|
|
166
|
+
### Package Collector
|
|
167
|
+
|
|
168
|
+
Parses:
|
|
169
|
+
|
|
170
|
+
```text
|
|
171
|
+
/var/log/pacman.log
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Tracks:
|
|
175
|
+
|
|
176
|
+
* installed packages
|
|
177
|
+
* removed packages
|
|
178
|
+
* upgraded packages
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### Service Collector
|
|
183
|
+
|
|
184
|
+
Uses:
|
|
185
|
+
|
|
186
|
+
```text
|
|
187
|
+
systemctl
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Tracks:
|
|
191
|
+
|
|
192
|
+
* started services
|
|
193
|
+
* stopped services
|
|
194
|
+
* restarted services
|
|
195
|
+
* failed services
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
### Performance Collector
|
|
200
|
+
|
|
201
|
+
Monitors:
|
|
202
|
+
|
|
203
|
+
* CPU usage
|
|
204
|
+
* memory usage
|
|
205
|
+
* disk usage
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
### Shell Collector
|
|
210
|
+
|
|
211
|
+
Reads:
|
|
212
|
+
|
|
213
|
+
```text
|
|
214
|
+
~/.bash_history
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Tracks executed commands.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
### File Collector
|
|
222
|
+
|
|
223
|
+
Uses:
|
|
224
|
+
|
|
225
|
+
```text
|
|
226
|
+
watchdog
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Tracks:
|
|
230
|
+
|
|
231
|
+
* created files
|
|
232
|
+
* modified files
|
|
233
|
+
* deleted files
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Roadmap
|
|
238
|
+
|
|
239
|
+
* systemd service support
|
|
240
|
+
* daemon mode
|
|
241
|
+
* multi-distribution package support
|
|
242
|
+
* export reports
|
|
243
|
+
* weekly summaries
|
|
244
|
+
* interactive TUI
|
|
245
|
+
* notifications
|
|
246
|
+
* command learning mode
|
|
247
|
+
* performance history graphs
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## License
|
|
252
|
+
|
|
253
|
+
MIT License
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Author
|
|
258
|
+
|
|
259
|
+
Created by DarkGlitch.
|
|
260
|
+
|
|
261
|
+
Rewind aims to become a personal timeline for Linux systems.
|
|
File without changes
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# collect.py
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
sys.path.append(
|
|
8
|
+
str(Path(__file__).resolve().parent.parent)
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
from database import Database
|
|
12
|
+
|
|
13
|
+
from collectors.packages import PackageCollector
|
|
14
|
+
from collectors.services import ServiceCollector
|
|
15
|
+
from collectors.performance import PerformanceCollector
|
|
16
|
+
from collectors.shell import ShellCollector
|
|
17
|
+
from collectors.files import FileCollector
|
|
18
|
+
|
|
19
|
+
def start(stop_event=None):
|
|
20
|
+
db = Database()
|
|
21
|
+
|
|
22
|
+
packages = PackageCollector()
|
|
23
|
+
services = ServiceCollector()
|
|
24
|
+
performance = PerformanceCollector()
|
|
25
|
+
shell = ShellCollector()
|
|
26
|
+
|
|
27
|
+
# Start file monitoring (queue-based) in parallel with other collectors.
|
|
28
|
+
# Watching / can be noisy; change watch_root if needed.
|
|
29
|
+
file_collector = FileCollector(watch_path="/", recursive=True)
|
|
30
|
+
file_collector.start()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
print("Rewind monitor started.")
|
|
34
|
+
|
|
35
|
+
while True:
|
|
36
|
+
if stop_event is not None and stop_event.is_set():
|
|
37
|
+
break
|
|
38
|
+
|
|
39
|
+
all_events = []
|
|
40
|
+
|
|
41
|
+
all_events.extend(packages.read_new_events())
|
|
42
|
+
all_events.extend(services.check_changes())
|
|
43
|
+
all_events.extend(performance.check())
|
|
44
|
+
all_events.extend(shell.read_new_commands())
|
|
45
|
+
all_events.extend(file_collector.read_new_events())
|
|
46
|
+
|
|
47
|
+
db.add_events(all_events)
|
|
48
|
+
|
|
49
|
+
time.sleep(10)
|
|
50
|
+
|
|
51
|
+
file_collector.stop()
|
|
52
|
+
db.close()
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import time
|
|
3
|
+
import threading
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from queue import Queue, Empty
|
|
6
|
+
|
|
7
|
+
from watchdog.observers import Observer
|
|
8
|
+
from watchdog.events import FileSystemEventHandler
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class FileCollector(FileSystemEventHandler):
|
|
12
|
+
"""Queue-based file change collector.
|
|
13
|
+
|
|
14
|
+
Produces events into an internal Queue so the main loop can batch them.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
watch_path: str | Path = "/",
|
|
20
|
+
recursive: bool = True,
|
|
21
|
+
throttle_seconds: float = 2.0,
|
|
22
|
+
):
|
|
23
|
+
super().__init__()
|
|
24
|
+
self.watch_path = Path(watch_path)
|
|
25
|
+
self.recursive = recursive
|
|
26
|
+
|
|
27
|
+
self._queue: Queue = Queue()
|
|
28
|
+
|
|
29
|
+
# Debounce by (event_type, src_path) and only emit once per throttle window.
|
|
30
|
+
self.throttle_seconds = throttle_seconds
|
|
31
|
+
self._last_emitted = {}
|
|
32
|
+
|
|
33
|
+
self._observer: Observer | None = None
|
|
34
|
+
|
|
35
|
+
def start(self):
|
|
36
|
+
if self._observer is not None:
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
observer = Observer()
|
|
40
|
+
observer.schedule(self, str(self.watch_path), recursive=self.recursive)
|
|
41
|
+
observer.start()
|
|
42
|
+
self._observer = observer
|
|
43
|
+
|
|
44
|
+
def stop(self):
|
|
45
|
+
if self._observer is None:
|
|
46
|
+
return
|
|
47
|
+
self._observer.stop()
|
|
48
|
+
self._observer.join(timeout=5)
|
|
49
|
+
self._observer = None
|
|
50
|
+
|
|
51
|
+
def _enqueue(self, event_type: str, src_path: str):
|
|
52
|
+
now = time.time()
|
|
53
|
+
key = (event_type, src_path)
|
|
54
|
+
last = self._last_emitted.get(key)
|
|
55
|
+
if last is not None and (now - last) < self.throttle_seconds:
|
|
56
|
+
return
|
|
57
|
+
|
|
58
|
+
self._last_emitted[key] = now
|
|
59
|
+
title = f"{event_type}: {src_path}"
|
|
60
|
+
|
|
61
|
+
# Keep it consistent with other collectors.
|
|
62
|
+
self._queue.put({
|
|
63
|
+
"category": "file",
|
|
64
|
+
"title": title,
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
def on_modified(self, event):
|
|
68
|
+
if event.is_directory:
|
|
69
|
+
return
|
|
70
|
+
self._enqueue("Modified", event.src_path)
|
|
71
|
+
|
|
72
|
+
def on_created(self, event):
|
|
73
|
+
if event.is_directory:
|
|
74
|
+
return
|
|
75
|
+
self._enqueue("Created", event.src_path)
|
|
76
|
+
|
|
77
|
+
def on_deleted(self, event):
|
|
78
|
+
if event.is_directory:
|
|
79
|
+
return
|
|
80
|
+
self._enqueue("Deleted", event.src_path)
|
|
81
|
+
|
|
82
|
+
def read_new_events(self, max_events: int = 500):
|
|
83
|
+
events = []
|
|
84
|
+
for _ in range(max_events):
|
|
85
|
+
try:
|
|
86
|
+
events.append(self._queue.get_nowait())
|
|
87
|
+
except Empty:
|
|
88
|
+
break
|
|
89
|
+
return events
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# Backwards-compatible function kept for older imports.
|
|
93
|
+
# This project primarily uses FileCollector.
|
|
94
|
+
|
|
95
|
+
def monitor(path: str | Path):
|
|
96
|
+
collector = FileCollector(watch_path=path)
|
|
97
|
+
collector.start()
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
while True:
|
|
101
|
+
time.sleep(1)
|
|
102
|
+
except KeyboardInterrupt:
|
|
103
|
+
collector.stop()
|
|
104
|
+
|