Skip to content

Instantly share code, notes, and snippets.

@zoranzaric
Created August 6, 2011 16:01
Show Gist options
  • Save zoranzaric/1129461 to your computer and use it in GitHub Desktop.
Save zoranzaric/1129461 to your computer and use it in GitHub Desktop.
#/usr/bin/env python
"""
This is a simple prototype for a bup inotify command. It watches a directory
and backs its created, modified, or deleted content up.
Requirements:
- bup
Get it from http://github.com/apenwarr/bup
- pyinotify
Use a OS package or `pip install pyinotify`
"""
import pyinotify
import shlex
import subprocess
import os
from Queue import Queue
from time import time
INDEX_CMD = "bup -d %s index %s"
SAVE_CMD = "bup -d %s save -q -n %s %s"
WATCH_DIR = '/home/zz/tmp/inotify/'
BUP_DIR = '/home/zz/tmp/stas/.bup'
BACKUP_TARGET = 'inotify'
QUEUE_TIMEOUT = 1# seconds
wm = pyinotify.WatchManager()
mask = pyinotify.IN_DELETE | pyinotify.IN_CREATE | pyinotify.IN_MODIFY
def backup(path):
p = subprocess.Popen(shlex.split(INDEX_CMD % (BUP_DIR, path)))
p.wait()
p = subprocess.Popen(shlex.split(SAVE_CMD % (BUP_DIR, BACKUP_TARGET, path)))
p.wait()
def WORK(timeout=1):
"""
Backup paths in queue.
Only use the last event for a path. If a path is created and deleted
immedialty it is ignored. Backup all paths in one bup call.
TODO the timeout should be handled differently.
"""
global last_work
if last_work + timeout < time():
paths = dict()
while not q.empty():
event, path = q.get()
if event == 'create':
paths[path] = 'create'
elif event == 'modify':
paths[path] = 'modify'
elif event == 'delete':
if path in paths:
last_action = paths[path]
if last_action != 'delete':
del(paths[path])
else:
paths[path] = 'delete'
backup_paths = []
for path, event in paths.iteritems():
if event == 'create' or event == 'modify':
# TODO new directories should be added to the watchlist
backup_paths.append(path)
elif event == 'delete':
backup_paths.append(os.path.join(event.pathname,
os.path.pardir))
if len(backup_paths) > 0:
print " ".join(backup_paths)
backup(" ".join(backup_paths))
last_work = time()
class EventHandler(pyinotify.ProcessEvent):
def process_IN_CREATE(self, event):
print "Creating:", event.pathname
q.put(('create', event.pathname))
WORK()
def process_IN_DELETE(self, event):
print "Removing:", event.pathname
# if a file or directory is deleted we have to index and save its parent
q.put(('delete', event.pathname))
WORK()
def process_IN_MODIFY(self, event):
print "Modifying:", event.pathname
q.put(('modify', event.pathname))
WORK()
handler = EventHandler()
notifier = pyinotify.Notifier(wm, handler, timeout=10)
wdd = wm.add_watch(WATCH_DIR, mask, rec=True)
backup(WATCH_DIR)
q = Queue()
last_work = 0
print "Starting loop..."
notifier.loop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment