Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc5b254c

Browse files
committed
add watchdog tutorial
1 parent707a12b commitc5b254c

File tree

5 files changed

+289
-0
lines changed

5 files changed

+289
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#[How to Create a Watchdog in Python](https://www.thepythoncode.com/article/create-a-watchdog-in-python)
2+
To run this:
3+
-`pip3 install -r requirements.txt`
4+
-`python3 controller.py --help`
5+
**Output:**
6+
```
7+
usage: controller.py [-h] [-d WATCH_DELAY] [-r] [-p PATTERN] [--watch-directories] path
8+
9+
Watchdog script for watching for files & directories' changes
10+
11+
positional arguments:
12+
path
13+
14+
optional arguments:
15+
-h, --help show this help message and exit
16+
-d WATCH_DELAY, --watch-delay WATCH_DELAY
17+
Watch delay, default is 1
18+
-r, --recursive Whether to recursively watch for the path's children, default is False
19+
-p PATTERN, --pattern PATTERN
20+
Pattern of files to watch, default is .txt,.trc,.log
21+
--watch-directories Whether to watch directories, default is True
22+
```
23+
- For example, watching the path`E:\watchdog` recursively for log and text files:
24+
```
25+
python controller.py E:\watchdog --recursive -p .txt,.log
26+
```
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
importdatetime
2+
frompygtailimportPygtail
3+
4+
# Loading the package called re from the RegEx Module in order to work with Regular Expressions
5+
importre
6+
7+
8+
classFileChecker:
9+
def__init__(self,exceptionPattern):
10+
self.exceptionPattern=exceptionPattern
11+
12+
defcheckForException(self,event,path):
13+
# Get current date and time according to the specified format.
14+
now= (datetime.datetime.now()).strftime("%Y-%m-%d %H:%M:%S")
15+
# Read the lines of the file (specified in the path) that have not been read yet
16+
# Meaning by that it will start from the point where it was last stopped.
17+
fornum,lineinenumerate(Pygtail(path),1):
18+
# Remove leading and trailing whitespaces including newlines.
19+
line=line.strip()
20+
# Return all non-overlapping matches of the values specified in the Exception Pattern.
21+
# The line is scanned from left to right and matches are returned in the oder found.
22+
iflineandany(re.findall('|'.join(self.exceptionPattern),line,flags=re.I|re.X)):
23+
# Observation Detected
24+
type='observation'
25+
msg=f"{now} --{event.event_type} -- File:{path} -- Observation:{line}"
26+
yieldtype,msg
27+
elifline:
28+
# No Observation Detected
29+
type='msg'
30+
msg=f"{now} --{event.event_type} -- File:{path}"
31+
yieldtype,msg
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Application configuration File
2+
################################
3+
4+
# Directory To Watch, If not specified, the following value will be considered explicitly.
5+
WATCH_DIRECTORY="C:\\SCRIPTS"
6+
7+
# Delay Between Watch Cycles In Seconds
8+
WATCH_DELAY=1
9+
10+
# Check The WATCH_DIRECTORY and its children
11+
WATCH_RECURSIVELY=False
12+
13+
# whether to watch for directory events
14+
DO_WATCH_DIRECTORIES=True
15+
16+
# Patterns of the files to watch
17+
WATCH_PATTERN='.txt,.trc,.log'
18+
19+
LOG_FILES_EXTENSIONS= ('.txt','.log','.trc')
20+
21+
# Patterns for observations
22+
EXCEPTION_PATTERN= ['EXCEPTION','FATAL','ERROR']
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
# The Observer watches for any file change and then dispatches the respective events to an event handler.
2+
fromwatchdog.observersimportObserver
3+
# The event handler will be notified when an event occurs.
4+
fromwatchdog.eventsimportFileSystemEventHandler
5+
importtime
6+
importconfig
7+
importos
8+
fromcheckerimportFileChecker
9+
importdatetime
10+
fromcoloramaimportFore,Style,init
11+
12+
init()
13+
14+
GREEN=Fore.GREEN
15+
BLUE=Fore.BLUE
16+
RED=Fore.RED
17+
YELLOW=Fore.YELLOW
18+
19+
event2color= {
20+
"created":GREEN,
21+
"modified":BLUE,
22+
"deleted":RED,
23+
"moved":YELLOW,
24+
}
25+
26+
27+
defprint_with_color(s,color=Fore.WHITE,brightness=Style.NORMAL,**kwargs):
28+
"""Utility function wrapping the regular `print()` function
29+
but with colors and brightness"""
30+
print(f"{brightness}{color}{s}{Style.RESET_ALL}",**kwargs)
31+
32+
33+
# Class that inherits from FileSystemEventHandler for handling the events sent by the Observer
34+
classLogHandler(FileSystemEventHandler):
35+
36+
def__init__(self,watchPattern,exceptionPattern,doWatchDirectories):
37+
self.watchPattern=watchPattern
38+
self.exceptionPattern=exceptionPattern
39+
self.doWatchDirectories=doWatchDirectories
40+
# Instantiate the checker
41+
self.fc=FileChecker(self.exceptionPattern)
42+
43+
defon_any_event(self,event):
44+
now= (datetime.datetime.now()).strftime("%Y-%m-%d %H:%M:%S")
45+
# print("event happened:", event)
46+
# To Observe files only not directories
47+
ifnotevent.is_directory:
48+
# To cater for the on_move event
49+
path=event.src_path
50+
ifhasattr(event,'dest_path'):
51+
path=event.dest_path
52+
# Ensure that the file extension is among the pre-defined ones.
53+
ifpath.endswith(self.watchPattern):
54+
msg=f"{now} --{event.event_type} -- File:{path}"
55+
ifevent.event_typein ('modified','created','moved'):
56+
# check for exceptions in log files
57+
ifpath.endswith(config.LOG_FILES_EXTENSIONS):
58+
fortype,msginself.fc.checkForException(event=event,path=path):
59+
print_with_color(
60+
msg,color=event2color[event.event_type],brightness=Style.BRIGHT)
61+
else:
62+
print_with_color(
63+
msg,color=event2color[event.event_type])
64+
else:
65+
print_with_color(msg,color=event2color[event.event_type])
66+
elifself.doWatchDirectories:
67+
msg=f"{now} --{event.event_type} -- Folder:{event.src_path}"
68+
print_with_color(msg,color=event2color[event.event_type])
69+
70+
defon_modified(self,event):
71+
pass
72+
73+
defon_deleted(self,event):
74+
pass
75+
76+
defon_created(self,event):
77+
pass
78+
79+
defon_moved(self,event):
80+
pass
81+
82+
83+
classLogWatcher:
84+
# Initialize the observer
85+
observer=None
86+
# Initialize the stop signal variable
87+
stop_signal=0
88+
89+
# The observer is the class that watches for any file system change and then dispatches the event to the event handler.
90+
def__init__(self,watchDirectory,watchDelay,watchRecursively,watchPattern,doWatchDirectories,exceptionPattern):
91+
# Initialize variables in relation
92+
self.watchDirectory=watchDirectory
93+
self.watchDelay=watchDelay
94+
self.watchRecursively=watchRecursively
95+
self.watchPattern=watchPattern
96+
self.doWatchDirectories=doWatchDirectories
97+
self.exceptionPattern=exceptionPattern
98+
99+
# Create an instance of watchdog.observer
100+
self.observer=Observer()
101+
# The event handler is an object that will be notified when something happens to the file system.
102+
self.event_handler=LogHandler(
103+
watchPattern,exceptionPattern,self.doWatchDirectories)
104+
105+
defschedule(self):
106+
print("Observer Scheduled:",self.observer.name)
107+
# Call the schedule function via the Observer instance attaching the event
108+
self.observer.schedule(
109+
self.event_handler,self.watchDirectory,recursive=self.watchRecursively)
110+
111+
defstart(self):
112+
print("Observer Started:",self.observer.name)
113+
self.schedule()
114+
# Start the observer thread and wait for it to generate events
115+
now= (datetime.datetime.now()).strftime("%Y-%m-%d %H:%M:%S")
116+
msg=f"Observer:{self.observer.name} - Started On:{now}"
117+
print(msg)
118+
119+
msg= (
120+
f"Watching{'Recursively'ifself.watchRecursivelyelse'Non-Recursively'}:{self.watchPattern}"
121+
f" -- Folder:{self.watchDirectory} -- Every:{self.watchDelay}(sec) -- For Patterns:{self.exceptionPattern}"
122+
)
123+
print(msg)
124+
self.observer.start()
125+
126+
defrun(self):
127+
print("Observer is running:",self.observer.name)
128+
self.start()
129+
try:
130+
whileTrue:
131+
time.sleep(self.watchDelay)
132+
133+
ifself.stop_signal==1:
134+
print(
135+
f"Observer stopped:{self.observer.name} stop signal:{self.stop_signal}")
136+
self.stop()
137+
break
138+
except:
139+
self.stop()
140+
self.observer.join()
141+
142+
defstop(self):
143+
print("Observer Stopped:",self.observer.name)
144+
145+
now= (datetime.datetime.now()).strftime("%Y-%m-%d %H:%M:%S")
146+
msg=f"Observer:{self.observer.name} - Stopped On:{now}"
147+
print(msg)
148+
self.observer.stop()
149+
self.observer.join()
150+
151+
definfo(self):
152+
info= {
153+
'observerName':self.observer.name,
154+
'watchDirectory':self.watchDirectory,
155+
'watchDelay':self.watchDelay,
156+
'watchRecursively':self.watchRecursively,
157+
'watchPattern':self.watchPattern,
158+
}
159+
returninfo
160+
161+
162+
defis_dir_path(path):
163+
"""Utility function to check whether a path is an actual directory"""
164+
ifos.path.isdir(path):
165+
returnpath
166+
else:
167+
raiseNotADirectoryError(path)
168+
169+
170+
if__name__=="__main__":
171+
importargparse
172+
parser=argparse.ArgumentParser(
173+
description="Watchdog script for watching for files & directories' changes")
174+
parser.add_argument("path",
175+
default=config.WATCH_DIRECTORY,
176+
type=is_dir_path,
177+
)
178+
parser.add_argument("-d","--watch-delay",
179+
help=f"Watch delay, default is{config.WATCH_DELAY}",
180+
default=config.WATCH_DELAY,
181+
type=int,
182+
)
183+
parser.add_argument("-r","--recursive",
184+
action="store_true",
185+
help=f"Whether to recursively watch for the path's children, default is{config.WATCH_RECURSIVELY}",
186+
default=config.WATCH_RECURSIVELY,
187+
)
188+
parser.add_argument("-p","--pattern",
189+
help=f"Pattern of files to watch, default is{config.WATCH_PATTERN}",
190+
default=config.WATCH_PATTERN,
191+
)
192+
parser.add_argument("--watch-directories",
193+
action="store_true",
194+
help=f"Whether to watch directories, default is{config.DO_WATCH_DIRECTORIES}",
195+
default=config.DO_WATCH_DIRECTORIES,
196+
)
197+
# parse the arguments
198+
args=parser.parse_args()
199+
# define & launch the log watcher
200+
log_watcher=LogWatcher(
201+
watchDirectory=args.path,
202+
watchDelay=args.watch_delay,
203+
watchRecursively=args.recursive,
204+
watchPattern=tuple(args.pattern.split(",")),
205+
doWatchDirectories=args.watch_directories,
206+
exceptionPattern=config.EXCEPTION_PATTERN,
207+
)
208+
log_watcher.run()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Pygtail==0.11.1
2+
watchdog==2.1.1

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp