From b57c9e7b7775337e4067cc99418f95efa0701b15 Mon Sep 17 00:00:00 2001 From: Kload Date: Fri, 6 Dec 2013 11:01:43 +0000 Subject: [PATCH] Log reader --- action_map.yml | 7 ++++++ yunohost_service.py | 56 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/action_map.yml b/action_map.yml index 6666c8ca..7a55027f 100644 --- a/action_map.yml +++ b/action_map.yml @@ -587,6 +587,13 @@ service: nargs: "*" metavar: NAME + ### service_log() + log: + action_help: Show status information about one or more services (all by default) + arguments: + name: + help: Service name to log + ############################# # Firewall # diff --git a/yunohost_service.py b/yunohost_service.py index edae4106..3f04d101 100644 --- a/yunohost_service.py +++ b/yunohost_service.py @@ -143,6 +143,37 @@ def service_status(names=None): return result +def service_log(name): + """ + Log every log files of a service + + Keyword argument: + name -- Services name to log + + """ + services = _get_services() + + if name not in services.keys(): + raise YunoHostError(1, _("Unknown service '%s'") % service) + + if 'log' in services[name]: + log_list = services[name]['log'] + result = {} + if not isinstance(log_list, list): + log_list = [log_list] + + for log_path in log_list: + if os.path.isdir(log_path): + for log in [ f for f in os.listdir(log_path) if os.path.isfile(os.path.join(log_path, f)) and f[-4:] == '.log' ]: + result[os.path.join(log_path, log)] = _tail(os.path.join(log_path, log), 50) + else: + result[log_path] = _tail(log_path, 50) + else: + raise YunoHostError(1, _("Nothing to log for service '%s'") % name) + + return result + + def _run_service_command(action, service): """ Run services management command (start, stop, enable, disable) @@ -184,3 +215,28 @@ def _get_services(): with open('/etc/yunohost/services.yml', 'r') as f: services = yaml.load(f) return services + + +def _tail(file, n, offset=None): + """Reads a n lines from f with an offset of offset lines. The return + value is a tuple in the form ``(lines, has_more)`` where `has_more` is + an indicator that is `True` if there are more lines in the file. + """ + avg_line_length = 74 + to_read = n + (offset or 0) + + with open(file, 'r') as f: + while 1: + try: + f.seek(-(avg_line_length * to_read), 2) + except IOError: + # woops. apparently file is smaller than what we want + # to step back, go to the beginning instead + f.seek(0) + pos = f.tell() + lines = f.read().splitlines() + if len(lines) >= to_read or pos == 0: + return lines[-to_read:offset and -offset or None] + #return lines[-to_read:offset and -offset or None], \ + # len(lines) > to_read or pos > 0 + avg_line_length *= 1.3