diff options
Diffstat (limited to 'monitor.py')
-rw-r--r-- | monitor.py | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/monitor.py b/monitor.py new file mode 100644 index 0000000..7ae1266 --- /dev/null +++ b/monitor.py @@ -0,0 +1,261 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Logger Script +# +# Copyright (c) 2011 - Sebastian Silva <sebastian@somosazucar.org> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +#from sugar.datastore import datastore +#from sugar import profile +import sys,csv,os,shutil +from time import localtime, strftime, time, ctime, altzone, mktime, sleep +from datetime import datetime +from subprocess import Popen,PIPE,STDOUT +try: + from sqlite3 import dbapi2 as sqlite +except: + try: + from pysqlite2 import dbapi2 as sqlite + except: + print "Advertencia: Imposible encontrar bilbiotecas pysqlite." + +####################################################### + +def wait(time_lapse): + sleep(time_lapse) + +#def wait(time_lapse): +# """ Implementa un "sleep timer" compatible con GTK """ +# time_start = time() +# time_end = (time_start + time_lapse) +# +# while time_end > time(): +# while gtk.events_pending(): +# gtk.main_iteration() + +def execute_cmd(cmd): + """ Ejecuta un comando de la terminal y retorna el + output del comando. + """ + p = Popen(cmd, shell=True, bufsize=0, + stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True) + (child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout) + + return child_stdout_and_stderr.read() + +def _read_file(path): + """ + Esta función lee y retorna el contenido + de archivos de texto + """ + if os.access(path, os.R_OK) == 0: + return "n/d" + + fd = open(path, 'r') + value = fd.read() + fd.close() + if value: + value = value.strip('\n') + return value + else: + print "Error leyendo "+path + return None + +class Data_general: + """ + Obtenemos y almacenamos datos para registrar + """ + def __init__(self): + self.retrieved = False + self.events = {} + + def event(self, hora, texto): + try: + if self.events[hora]: + self.events[hora+1] = [ctime(hora), texto ] + except KeyError: + self.events[hora] = [ctime(hora), texto ] + + def collect_logs(self): + """ + recolecta la info de los logs de los historiales. + """ + log_dir = os.environ['HOME']+"/.sugar/default/logs" + if not os.path.exists(log_dir): + log_dir = "/home/olpc/.sugar/default/logs" + if not os.path.exists(log_dir): + return None + + # Navegar recursivamente los directorios de logs + stack = [log_dir] + mtime = 0 + while stack: + directory = stack.pop() + for base in os.listdir(directory): + name = os.path.join(directory, base) + if os.path.isdir(name): + if not os.path.islink(name): + stack.append(name) + else: + mtime = os.path.getmtime(name) + creation_time = os.path.getctime(name) + # nota: creation time no es correcto pq los logs han sido movidos a subcarpetas + this_dir = os.path.split(os.path.dirname(name))[1] + if this_dir == "logs": #estamos mirando la sesión recien comenzada + this_dir = "" + if base == "shell.log": + pass + elif base == "datastore.log": + pass + elif base == "presenceservice.log": + pass + else: + self.event(mtime, "LOG: Ultima actividad en " + name) + else: #estamos mirando una sesión anterior + if base == "datastore.log": + pass + elif base == "presenceservice.log": + self.event(mtime, "LOG: *** %s - probable inicio de sesión" % name ) + elif base == "shell.log": + self.event(mtime, "LOG: Ultima actividad en log de shell, posible fin de sesión: " + name) + + else: + self.event(mtime, "LOG: Ultima actividad en " + name) + + # Ahora vamos a iterar por todos los historiales de Navegador / Wikipedia + isolation_dir = "/home/olpc/isolation/1/gid_to_data_dir" + if not os.path.exists(isolation_dir): + isolation_dir = "/home/olpc/.sugar/default" + if not os.path.exists(isolation_dir): + print "Imposible encontrar directorio de los registros del navegador." + return None + stack = [isolation_dir] + while stack: + directory = stack.pop() + try: + subdirs = os.listdir(directory) + except: + subdirs = [] + for base in subdirs: + name = os.path.join(directory, base) + if os.path.isdir(name): + if not os.path.islink(name): + stack.append(name) + else: + if base == "places.db": + shutil.copy (name, "/tmp") + tmpname = os.path.join("/tmp", base) + con = sqlite.connect(tmpname) + cur = con.cursor() + results = cur.execute ("select last_visit, uri, title, visits from places") + for r in results: + #item_timestamp = float(str(r[0])[:10]) + item_timestamp = mktime( + datetime.strptime(r[0], "%Y-%m-%d %H:%M:%S.%f").timetuple()) + if r[1][:27] == 'http://localhost:8000/wiki/': + self.event(item_timestamp, "WEB: (" + r[1] + ") - Articulo Wikipedia: " + r[1][27:] + " (vez %s)" % r[3]) + elif r[1][:31] == 'http://localhost:8000/search?q=': + self.event(item_timestamp, "WEB: (" + r[1] + ") - Se busca en Wikipedia: " + r[1][31:] + " (vez %s)" % r[3]) + elif r[1][:29] == 'http://localhost:8000/static/': + self.event(item_timestamp, "WEB: (" + r[1] + ") - Inicio de Wikipedia." + " (vez %s)" % r[3]) + else: + self.event(item_timestamp, "WEB: Navega a: (" + r[1] + ") (vez %s)" % r[3]) + con.close() + os.unlink(tmpname) + + return True + + def install_logger(self): + #copiamos el ejecutable + logdir = "/home/olpc/.logger" + + if not os.path.exists(logdir): + execute_cmd("mkdir -p "+logdir) + + logprog = os.path.join(logdir, "logger.py") + shutil.copy (sys.argv[0], logprog) + + #lo hacemos autoiniciar + already_installed = False + xsession = "/home/olpc/.xsession" + if os.path.exists(xsession): + contents = _read_file(xsession) + for line in contents.splitlines(): + if line == "python /home/olpc/.logger/logger.py &": + already_installed = True + + if not already_installed: + execute_cmd("echo 'python /home/olpc/.logger/logger.py &' >> " + xsession) + + def update_logger(self): + if self.collect_logs(): + logdir = "/home/olpc/.logger" + logfile = "historial.csv" + + logpath = os.path.join(logdir, logfile) + + if not os.path.exists(logpath): + execute_cmd("mkdir -p "+logdir) + mtime = 0 + else: + #Obtenemos la fecha de la ultima entrada en el log + lastlog = execute_cmd("tail -n1 "+logpath) + lastlog = lastlog.strip('\n') + try: + mtime = float(lastlog[-11:-1]) + except: + mtime = 0 + + size = os.path.getsize(logpath) + # poor mans logrotate + if size>262144: #limit 256k + if os.path.exists(logpath+"-3"): + execute_cmd("mv "+logpath+"-3 "+logpath+"-4") + if os.path.exists(logpath+"-2"): + execute_cmd("mv "+logpath+"-2 "+logpath+"-3") + if os.path.exists(logpath+"-1"): + execute_cmd("mv "+logpath+"-1 "+logpath+"-2") + execute_cmd("mv "+logpath+" "+logpath+"-1") + + s = os.statvfs(logdir) + free_disk_in_mb = (s.f_bsize * s.f_bavail)/(1024*1024) + + if free_disk_in_mb > 30: + fd = open(logpath,"a") + writer = csv.writer(fd, dialect='excel') + for ev in sorted(self.events): + if ev > mtime: + writer.writerow(self.events[ev]) + #print self.events[ev] + writer.writerow([ctime(time()), "LOGGER: Se actualizó registro de seguimiento *** " + str(int(time()))]) + #print ctime() + " updated " + str(int(time())) + #print ctime(mtime) + " :last log " + str(int(mtime)) + fd.close() + else: + print "Imposible cargar logs." + + +# Aquí comienza la ejecución +if os.path.split(sys.argv[0])[-1:][0]=='logger.py': + # Somos el sistema de seguimiento + dg = Data_general() + wait(30) + dg.update_logger() +elif os.path.split(sys.argv[0])[-1:][0]=='instalar.py': + print "Instalador." + dg = Data_general() + dg.install_logger() + dg.update_logger() + print "Se ha instalado el programa de seguimiento." |