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):
|
class FileMonitorCommand(Subcommand):
|
||||||
"""
|
"""
|
||||||
Interacts with the file monitor Windows service; called as ``edbob
|
Interacts with the file monitor service; called as ``edbob filemon``. This
|
||||||
filemon``. This command expects a subcommand; one of the following:
|
command expects a subcommand; one of the following:
|
||||||
|
|
||||||
* ``edbob filemon install``
|
|
||||||
* ``edbob filemon start``
|
* ``edbob filemon start``
|
||||||
* ``edbob filemon stop``
|
* ``edbob filemon stop``
|
||||||
|
|
||||||
|
On Windows platforms, the following additional subcommands are available:
|
||||||
|
|
||||||
|
* ``edbob filemon install``
|
||||||
* ``edbob filemon uninstall``
|
* ``edbob filemon uninstall``
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
@ -399,28 +402,46 @@ class FileMonitorCommand(Subcommand):
|
||||||
``cmd.exe`` as an Administrator in order to have sufficient rights to
|
``cmd.exe`` as an Administrator in order to have sufficient rights to
|
||||||
run the above commands.
|
run the above commands.
|
||||||
|
|
||||||
|
.. todo::
|
||||||
|
Verify the previous statement... (Maybe test with/out UAC?)
|
||||||
|
|
||||||
See :doc:`howto.use_filemon` for more information.
|
See :doc:`howto.use_filemon` for more information.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = 'filemon'
|
name = 'filemon'
|
||||||
description = "Manage the file monitor service on Windows"
|
description = "Manage the file monitor service"
|
||||||
|
|
||||||
def add_parser_args(self, parser):
|
def add_parser_args(self, parser):
|
||||||
subparsers = parser.add_subparsers(title='subcommands')
|
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 = subparsers.add_parser('start', help="Start service")
|
||||||
start.set_defaults(subcommand='start')
|
start.set_defaults(subcommand='start')
|
||||||
stop = subparsers.add_parser('stop', help="Stop service")
|
stop = subparsers.add_parser('stop', help="Stop service")
|
||||||
stop.set_defaults(subcommand='stop')
|
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):
|
def run(self, args):
|
||||||
from edbob.filemon import exec_server_command
|
if sys.platform == 'linux2':
|
||||||
exec_server_command(args.subcommand)
|
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):
|
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:
|
# 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])
|
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):
|
def monitor_win32(path, include_subdirs=False):
|
||||||
"""
|
"""
|
||||||
This is the workhorse of file monitoring on the Windows platform. It is a
|
This is the workhorse of file monitoring on the Windows platform. It is a
|
|
@ -32,9 +32,9 @@ import time
|
||||||
import Queue
|
import Queue
|
||||||
|
|
||||||
import edbob
|
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.win32 import file_is_free
|
||||||
from edbob.filemon import (MonitorProfile, WatcherWin32,
|
|
||||||
ACTION_CREATE, ACTION_UPDATE)
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
if sys.platform == 'win32': # docs should build for everyone
|
if sys.platform == 'win32': # docs should build for everyone
|
Loading…
Add table
Add a link
Reference in a new issue