from jinja2 import Environment, FileSystemLoader import subprocess from datetime import datetime, timedelta import os import sys import re if len(sys.argv) > 1: time_ago_arg = int(sys.argv[1]) book_path = f"/home/xpub/www/html/tl-dr/book_{time_ago_arg}.html" print(f"Going back in time by {time_ago_arg} days") else: print(f"Creating a book for today") book_path = f"/home/xpub/www/html/tl-dr/book.html" time_ago_arg = False #create the log directory path = "/home/xpub/www/html/tl-dr/log-books" if not os.path.exists(path): os.makedirs(path) if(time_ago_arg): now = datetime.today() - timedelta(days=time_ago_arg) else: now = datetime.today() book_name = "TL;DR_" + now.strftime("%B %dth %Y") print(f"making a book called {book_name}") def get_journalctl_on(): if time_ago_arg: return ["-S", f"{time_ago_arg + 1} days ago", "-U", f"{time_ago_arg} days ago"] else: return ["-S","today"] def create_all_logs_file(): list_logs = subprocess.run(["ls", "/home/xpub/www/html/tl-dr/log-books"], capture_output=True) with open("/home/xpub/www/html/tl-dr/log-books/all.txt", "w") as f: print(list_logs.stdout.decode('UTF-8').strip(), file=f) # Execute a command on the command line. Based = used for piped commands def run_command(command, based = False): result = subprocess.run(command, capture_output=True, input=based) result.check_returncode() stripped = result.stdout.decode('UTF-8').strip() if "No entries" in stripped: return "" else: return stripped # Run all the commands for getting the logs, and assign to variables print("Commands: statics") # These vars cannot go back in time if not time_ago_arg: since_last_boot = run_command(["uptime","-s"]) slb_date = datetime.strptime(since_last_boot, "%Y-%m-%d %H:%M:%S") time_since_last_boot = (now - slb_date).days device_info_grab = subprocess.run(["grep", 'Model' , "/proc/cpuinfo"], check=True, capture_output=True) device_info = run_command(['awk', '-F:', '{ print $2}'], based=device_info_grab.stdout) ip_address_show = subprocess.run(["ip", "addr", "show", "end0"], check=True, capture_output=True) ip_address = run_command(['awk', '$1 == "inet" {gsub(/\/.*$/, "", $2); print $2}' ], based=ip_address_show.stdout) list_active_services = run_command(["sudo", "service", "--status-all"]).splitlines() else: since_last_boot = False device_info = False ip_address = False time_since_last_boot = False list_active_services = False print("Commands: packages") dpkg_date = now.strftime("%Y-%m-%d") list_package_installs = subprocess.run(["grep","-E", dpkg_date + '.*install|install.*' + dpkg_date, "/var/log/dpkg.log"], capture_output=True).stdout.decode('UTF-8').splitlines() list_package_upgrade = subprocess.run(["grep","-E", dpkg_date + '.*upgrade|upgrade.*' + dpkg_date, "/var/log/dpkg.log"], capture_output=True).stdout.decode('UTF-8').splitlines() list_package_remove = subprocess.run(["grep","-E", dpkg_date + '.*remove|remove.*' + dpkg_date, "/var/log/dpkg.log"], capture_output=True).stdout.decode('UTF-8').splitlines() print("Commands: journalctl, this sometimes takes longer"); # journal_today = run_command(["sudo", "journalctl","_COMM=useradd", "_COMM=usermod", "_COMM=userdel","_COMM=groupremove", "_COMM=groupadd","-r", "--utc"] + get_journalctl_on()).splitlines() journal_today = subprocess.run(["sudo", "journalctl","_COMM=systemd-logind","_COMM=useradd", "_COMM=usermod", "_COMM=userdel","_COMM=groupremove", "_COMM=groupadd","-r", "--utc"] + get_journalctl_on(), check=True, capture_output=True) def get_last_user(log): if log: last = log[-1] result = re.findall(r"name=([^,]*)", users_created_today[-1]) return result[0] else: return False def get_kitchen_prints(): kitchen_date = now.strftime("%d/%b/%Y") try: cup_logs_today = subprocess.run(["sudo","grep","-E", kitchen_date, "/var/log/cups/access_log"], capture_output=True).stdout.decode('UTF-8').splitlines() return [log for log in cup_logs_today if 'Send-Document' in log] except subprocess.CalledProcessError as e: raise RuntimeError("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output)) return False try: groups_created = subprocess.run(['grep','groupadd'], capture_output=True, input=journal_today.stdout).stdout.decode('UTF-8').strip().splitlines() groups_removed = subprocess.run(['grep','groupremove'], capture_output=True, input=journal_today.stdout).stdout.decode('UTF-8').strip().splitlines() users_created_today = subprocess.run(['grep','useradd'], capture_output=True, input=journal_today.stdout).stdout.decode('UTF-8').strip().splitlines() user_modified = subprocess.run(['grep','usermod'], capture_output=True, input=journal_today.stdout).stdout.decode('UTF-8').strip().splitlines() user_deleted = subprocess.run(['grep','userdel'], capture_output=True, input=journal_today.stdout).stdout.decode('UTF-8').strip().splitlines() logins_today = subprocess.run(['grep','New session'], capture_output=True, input=journal_today.stdout).stdout.decode('UTF-8').strip().splitlines() last_user_added_name = get_last_user(users_created_today) except subprocess.CalledProcessError as e: raise RuntimeError("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output)) print("Got all commands data"); # loading the jinja template environment env = Environment(loader=FileSystemLoader("/home/xpub/www/html/tl-dr/templates")) # loading the template (use template.jinja when generating the html webview) template = env.get_template("book.jinja") print("rendering the template") # rendering the template and storing the resultant text in variable output output = template.render( now = now.strftime("%B %dth %Y"), last_user_added_name=last_user_added_name if not last_user_added_name else False, since_last_boot=since_last_boot, list_package_installs=list_package_installs, list_package_upgrade=list_package_upgrade, list_package_remove=list_package_remove, device_info=device_info, days_since_last_boot = time_since_last_boot, kitchen_prints = get_kitchen_prints(), ip_address = ip_address, list_active_services = list_active_services, debian_version = run_command(["cat", "/etc/debian_version"]) if not time_ago_arg else False, hostname = run_command(["hostname","-i"]) if not time_ago_arg else False, groups_created = groups_created, groups_removed = groups_removed, users_created_today = users_created_today, user_modified = user_modified, user_deleted = user_deleted, logins_today = logins_today ) print("Storing the files"); # Export the html as book.html, which is used as an input for pandoc with open(book_path, "w") as f: print(output, file=f) if not time_ago_arg: subprocess.run(['sh', '/home/xpub/www/html/tl-dr/create_book.sh', book_name, book_path]) else: subprocess.run(['sh', '/home/xpub/www/html/tl-dr/create_book.sh', book_name, book_path]) print("Finished");