# -*- coding: utf-8 -*- """What log history actually exists, per site. Listing only, nothing downloaded. Paper 09 was parked on the assumption that the logs had rotated away. Before planning around that, this asks each host what it holds: which archives exist, how large they are, and how far back they go. It connects over FTPS, lists two directories, and disconnects. It downloads nothing, writes nothing and prints no credential. python log_inventory.py every site with a stored credential python log_inventory.py broikos.gr collectorcenter.gr """ import ftplib import glob import io import os import re import sys HTDOCS = r'C:\xampp\htdocs' LOG_DIRS = ('/logs', '/access-logs', '/tmp/awstats') def sites(): out = [] for path in sorted(glob.glob(os.path.join(HTDOCS, '*', 'ftp.md'))): out.append(os.path.basename(os.path.dirname(path))) return out def creds(site): """Host, user and password out of a note written by hand, in three formats. These files were written for a person, not a parser: one uses a scheme and Username/Password lines, one uses url/user/pass, one uses a markdown table. A parser that understands only the first reports the other sites as having no credential, which is a wrong answer about access rather than a missing file. """ text = io.open(os.path.join(HTDOCS, site, 'ftp.md'), encoding='utf-8', errors='replace').read() def field(*names): for n in names: m = re.search(r'(?im)^\s*\|?\s*%s\s*[:|]\s*\|?\s*([^\s|]+)' % n, text) if m: return m.group(1).strip('*` ') return None host = None m = re.search(r'https?://([^\s/]+)', text) if m: host = m.group(1) if not host: host = field('host', 'server', 'ftp host') if not host: m = re.search(r'(?m)^\s*([a-z0-9-]+\.[a-z.]{2,})\s*$', text) host = m.group(1) if m else site user = field('username', 'user', 'ftp user', 'login') pwd = field('password', 'pass', 'ftp password') if not (host and user and pwd): return None return host, user, pwd def listing(ftp, path): lines = [] try: ftp.retrlines('LIST %s' % path, lines.append) except ftplib.all_errors: return [] out = [] for line in lines: parts = line.split(maxsplit=8) if len(parts) < 9 or parts[8] in ('.', '..'): continue out.append((parts[8], int(parts[4]) if parts[4].isdigit() else 0, ' '.join(parts[5:8]))) return out def inspect(site): c = creds(site) if not c: print('%-22s no usable credential in ftp.md' % site) return host, user, pwd = c try: ftp = ftplib.FTP_TLS(timeout=40) ftp.connect(host, 21) ftp.login(user, pwd) ftp.prot_p() except Exception as exc: # noqa: BLE001 print('%-22s connect failed: %s' % (site, str(exc)[:70])) return found = {} for d in LOG_DIRS: entries = listing(ftp, d) if entries: found[d] = entries ftp.quit() if not found: print('%-22s no log directory reachable' % site) return for d, entries in found.items(): archives = [e for e in entries if e[0].endswith(('.gz', '.txt'))] total = sum(e[1] for e in archives) months = sorted({re.search(r'([A-Z][a-z]{2}-\d{4})', e[0]).group(1) for e in archives if re.search(r'([A-Z][a-z]{2}-\d{4})', e[0])}) print('%-22s %-14s %3d file(s), %6.1f MB%s' % (site, d, len(archives), total / 1e6, (' months: %s .. %s' % (months[0], months[-1])) if months else '')) def main(argv): targets = argv[1:] or sites() print('%-22s %-14s %s' % ('site', 'directory', 'what is there')) print('-' * 78) for s in targets: inspect(s) print('\nlisting only. Nothing was downloaded and nothing was changed.') return 0 if __name__ == '__main__': raise SystemExit(main(sys.argv))