add linux file monitor
This commit is contained in:
parent
b3b4e40bcf
commit
79c4bfa289
5 changed files with 202 additions and 31 deletions
|
@ -386,12 +386,15 @@ class DatabaseCommand(Subcommand):
|
|||
|
||||
class FileMonitorCommand(Subcommand):
|
||||
"""
|
||||
Interacts with the file monitor Windows service; called as ``edbob
|
||||
filemon``. This command expects a subcommand; one of the following:
|
||||
Interacts with the file monitor service; called as ``edbob filemon``. This
|
||||
command expects a subcommand; one of the following:
|
||||
|
||||
* ``edbob filemon install``
|
||||
* ``edbob filemon start``
|
||||
* ``edbob filemon stop``
|
||||
|
||||
On Windows platforms, the following additional subcommands are available:
|
||||
|
||||
* ``edbob filemon install``
|
||||
* ``edbob filemon uninstall``
|
||||
|
||||
.. note::
|
||||
|
@ -399,28 +402,46 @@ class FileMonitorCommand(Subcommand):
|
|||
``cmd.exe`` as an Administrator in order to have sufficient rights to
|
||||
run the above commands.
|
||||
|
||||
.. todo::
|
||||
Verify the previous statement... (Maybe test with/out UAC?)
|
||||
|
||||
See :doc:`howto.use_filemon` for more information.
|
||||
"""
|
||||
|
||||
name = 'filemon'
|
||||
description = "Manage the file monitor service on Windows"
|
||||
description = "Manage the file monitor service"
|
||||
|
||||
def add_parser_args(self, parser):
|
||||
subparsers = parser.add_subparsers(title='subcommands')
|
||||
install = subparsers.add_parser('install',
|
||||
help="Install (register) service")
|
||||
install.set_defaults(subcommand='install')
|
||||
uninstall = subparsers.add_parser('uninstall',
|
||||
help="Uninstall (unregister) service")
|
||||
uninstall.set_defaults(subcommand='remove')
|
||||
|
||||
start = subparsers.add_parser('start', help="Start service")
|
||||
start.set_defaults(subcommand='start')
|
||||
stop = subparsers.add_parser('stop', help="Stop service")
|
||||
stop.set_defaults(subcommand='stop')
|
||||
|
||||
if sys.platform == 'win32':
|
||||
install = subparsers.add_parser('install',
|
||||
help="Install (register) service")
|
||||
install.set_defaults(subcommand='install')
|
||||
uninstall = subparsers.add_parser('uninstall',
|
||||
help="Uninstall (unregister) service")
|
||||
uninstall.set_defaults(subcommand='remove')
|
||||
|
||||
def run(self, args):
|
||||
from edbob.filemon import exec_server_command
|
||||
exec_server_command(args.subcommand)
|
||||
if sys.platform == 'linux2':
|
||||
if args.subcommand == 'start':
|
||||
from edbob.filemon.linux import start_daemon
|
||||
start_daemon()
|
||||
elif args.subcommand == 'stop':
|
||||
from edbob.filemon.linux import stop_daemon
|
||||
stop_daemon()
|
||||
|
||||
elif sys.platform == 'win32':
|
||||
from edbob.filemon.win32 import exec_server_command
|
||||
exec_server_command(args.subcommand)
|
||||
|
||||
else:
|
||||
print "Sorry, file monitor is not supported on platform %s." % sys.platform
|
||||
|
||||
|
||||
class ShellCommand(Subcommand):
|
||||
|
|
46
edbob/filemon/__init__.py
Normal file
46
edbob/filemon/__init__.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
#
|
||||
# edbob -- Pythonic Software Framework
|
||||
# Copyright © 2010-2012 Lance Edgar
|
||||
#
|
||||
# This file is part of edbob.
|
||||
#
|
||||
# edbob is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# edbob is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with edbob. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
"""
|
||||
``edbob.filemon`` -- File Monitoring Service
|
||||
"""
|
||||
|
||||
import edbob
|
||||
from edbob.exceptions import ConfigError
|
||||
|
||||
|
||||
class MonitorProfile(object):
|
||||
"""
|
||||
This is a simple profile class, used to represent configuration of the file
|
||||
monitor service.
|
||||
"""
|
||||
|
||||
def __init__(self, key):
|
||||
self.key = key
|
||||
self.dirs = eval(edbob.config.require('edbob.filemon', '%s.dirs' % key))
|
||||
if not self.dirs:
|
||||
raise ConfigError('edbob.filemon', '%s.dirs' % key)
|
||||
self.actions = eval(edbob.config.require('edbob.filemon', '%s.actions' % key))
|
||||
if not self.actions:
|
||||
raise ConfigError('edbob.filemon', '%s.actions' % key)
|
120
edbob/filemon/linux.py
Normal file
120
edbob/filemon/linux.py
Normal file
|
@ -0,0 +1,120 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
#
|
||||
# edbob -- Pythonic Software Framework
|
||||
# Copyright © 2010-2012 Lance Edgar
|
||||
#
|
||||
# This file is part of edbob.
|
||||
#
|
||||
# edbob is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# edbob is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with edbob. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
"""
|
||||
``edbob.filemon.linux`` -- File Monitor for Linux
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import os.path
|
||||
import signal
|
||||
import pyinotify
|
||||
|
||||
import edbob
|
||||
from edbob.filemon import MonitorProfile
|
||||
|
||||
|
||||
class EventHandler(pyinotify.ProcessEvent):
|
||||
"""
|
||||
Event processor for file monitor daemon.
|
||||
"""
|
||||
|
||||
def my_init(self, actions=[], **kwargs):
|
||||
self.actions = actions
|
||||
|
||||
def process_IN_CREATE(self, event):
|
||||
self.perform_actions(event.pathname)
|
||||
|
||||
def process_IN_MOVED_TO(self, event):
|
||||
self.perform_actions(event.pathname)
|
||||
|
||||
def perform_actions(self, path):
|
||||
for action in self.actions:
|
||||
if isinstance(action, tuple):
|
||||
func = action[0]
|
||||
args = action[1:]
|
||||
else:
|
||||
func = action
|
||||
args = []
|
||||
func = edbob.load_spec(func)
|
||||
func(path, *args)
|
||||
|
||||
|
||||
def get_pid_path():
|
||||
"""
|
||||
Returns the path to the PID file for the file monitor daemon.
|
||||
"""
|
||||
|
||||
basename = os.path.basename(sys.argv[0])
|
||||
return '/tmp/%s_filemon.pid' % basename
|
||||
|
||||
|
||||
def start_daemon():
|
||||
"""
|
||||
Starts the file monitor daemon.
|
||||
"""
|
||||
|
||||
pid_path = get_pid_path()
|
||||
if os.path.exists(pid_path):
|
||||
print "File monitor is already running"
|
||||
return
|
||||
|
||||
wm = pyinotify.WatchManager()
|
||||
notifier = pyinotify.Notifier(wm)
|
||||
|
||||
monitored = {}
|
||||
keys = edbob.config.require('edbob.filemon', 'monitored')
|
||||
keys = keys.split(',')
|
||||
for key in keys:
|
||||
key = key.strip()
|
||||
monitored[key] = MonitorProfile(key)
|
||||
|
||||
mask = pyinotify.IN_CREATE | pyinotify.IN_MOVED_TO
|
||||
for profile in monitored.itervalues():
|
||||
for path in profile.dirs:
|
||||
wm.add_watch(path, mask, proc_fun=EventHandler(actions=profile.actions))
|
||||
|
||||
notifier.loop(daemonize=True, pid_file=pid_path)
|
||||
|
||||
|
||||
def stop_daemon():
|
||||
"""
|
||||
Stops the file monitor daemon.
|
||||
"""
|
||||
|
||||
pid_path = get_pid_path()
|
||||
if not os.path.exists(pid_path):
|
||||
print "File monitor is not running"
|
||||
return
|
||||
|
||||
f = open(pid_path)
|
||||
pid = f.read().strip()
|
||||
f.close()
|
||||
if not pid.isdigit():
|
||||
print "Hm, found bogus PID:", pid
|
||||
return
|
||||
|
||||
os.kill(int(pid), signal.SIGKILL)
|
||||
os.remove(pid_path)
|
|
@ -23,7 +23,7 @@
|
|||
################################################################################
|
||||
|
||||
"""
|
||||
``edbob.filemon`` -- File Monitoring Service
|
||||
``edbob.filemon.win32`` -- File Monitor for Windows
|
||||
"""
|
||||
|
||||
# Much of the Windows monitoring code below was borrowed from Tim Golden:
|
||||
|
@ -67,22 +67,6 @@ def exec_server_command(command):
|
|||
subprocess.call([sys.executable, server_path, command])
|
||||
|
||||
|
||||
class MonitorProfile(object):
|
||||
"""
|
||||
This is a simple profile class, used to represent configuration of the file
|
||||
monitor service.
|
||||
"""
|
||||
|
||||
def __init__(self, key):
|
||||
self.key = key
|
||||
self.dirs = eval(edbob.config.require('edbob.filemon', '%s.dirs' % key))
|
||||
if not self.dirs:
|
||||
raise ConfigError('edbob.filemon', '%s.dirs' % key)
|
||||
self.actions = eval(edbob.config.require('edbob.filemon', '%s.actions' % key))
|
||||
if not self.actions:
|
||||
raise ConfigError('edbob.filemon', '%s.actions' % key)
|
||||
|
||||
|
||||
def monitor_win32(path, include_subdirs=False):
|
||||
"""
|
||||
This is the workhorse of file monitoring on the Windows platform. It is a
|
|
@ -32,9 +32,9 @@ import time
|
|||
import Queue
|
||||
|
||||
import edbob
|
||||
from edbob.filemon import MonitorProfile
|
||||
from edbob.filemon.win32 import WatcherWin32, ACTION_CREATE, ACTION_UPDATE
|
||||
from edbob.win32 import file_is_free
|
||||
from edbob.filemon import (MonitorProfile, WatcherWin32,
|
||||
ACTION_CREATE, ACTION_UPDATE)
|
||||
|
||||
import sys
|
||||
if sys.platform == 'win32': # docs should build for everyone
|
Loading…
Add table
Add a link
Reference in a new issue