| #!/usr/bin/env python3 |
| |
| from pathlib import Path |
| import subprocess |
| import sys |
| from systemd import journal |
| import uuid |
| |
| def _compact_uuid(x): |
| return str(x).replace('-', '') |
| |
| def main(remote_directory, output_directory): |
| j = journal.Reader(path=remote_directory) |
| j.add_match('MESSAGE_ID=d9b373ed55a64feb8242e02dbe79a49c') |
| j.add_match('SYSLOG_IDENTIFIER=systemd') |
| j.seek_tail() |
| j.get_previous() |
| while True: |
| j.wait() |
| for entry in j: |
| try: |
| hostname = entry['_HOSTNAME'] |
| machine = entry['_MACHINE_ID'] |
| bootid = entry['_BOOT_ID'] |
| unit = entry['UNIT'] |
| result = entry['UNIT_RESULT'] |
| t = entry['__REALTIME_TIMESTAMP'] |
| except KeyError as e: |
| print(f'Exception: {type(e)}: {e}') |
| continue |
| print(f'{hostname} ({machine}): {unit} made a boo-boo: {result}') |
| sanitized_hostname = ''.join((x if x.isalnum() or x in ('-', '_', '.') else '_'+hex(ord(x))[2:]+'_') for x in hostname) |
| output_filename = output_directory / ('crash-' + sanitized_hostname + '-' + _compact_uuid(uuid.uuid4()) + '.journal') |
| reader = ('journalctl', |
| '-D', remote_directory, |
| # Python formats UUIDs with dashes, and journalctl doesn't accept that |
| '_MACHINE_ID=' + _compact_uuid(machine), |
| '_BOOT_ID=' + _compact_uuid(bootid), |
| '--since', '-1m', |
| '-o', 'export') |
| writer = ('/lib/systemd/systemd-journal-remote', |
| '-o', output_filename, |
| '--split-mode=none', |
| '-') |
| reader_proc = subprocess.Popen(reader, stdout=subprocess.PIPE) |
| writer_proc = subprocess.Popen(writer, stdin=reader_proc.stdout) |
| reader_proc.wait() |
| writer_proc.wait() |
| print(f' -> wrote to {output_filename}') |
| subprocess.Popen(('journalctl', '--file', output_filename, '-p4', '-o', 'cat'), |
| stdout=open(str(output_filename) + '.txt', 'w')).wait() |
| |
| if __name__ == '__main__': |
| main(sys.argv[1], Path(sys.argv[2])) |