Jan Kundrát | dc6e772 | 2024-03-14 23:13:41 +0100 | [diff] [blame^] | 1 | #!/usr/bin/env python3 |
| 2 | |
| 3 | from pathlib import Path |
| 4 | import subprocess |
| 5 | import sys |
| 6 | from systemd import journal |
| 7 | import uuid |
| 8 | |
| 9 | def _compact_uuid(x): |
| 10 | return str(x).replace('-', '') |
| 11 | |
| 12 | def main(remote_directory, output_directory): |
| 13 | j = journal.Reader(path=remote_directory) |
| 14 | j.add_match('MESSAGE_ID=d9b373ed55a64feb8242e02dbe79a49c') |
| 15 | j.add_match('SYSLOG_IDENTIFIER=systemd') |
| 16 | j.seek_tail() |
| 17 | j.get_previous() |
| 18 | while True: |
| 19 | j.wait() |
| 20 | for entry in j: |
| 21 | try: |
| 22 | hostname = entry['_HOSTNAME'] |
| 23 | machine = entry['_MACHINE_ID'] |
| 24 | bootid = entry['_BOOT_ID'] |
| 25 | unit = entry['UNIT'] |
| 26 | result = entry['UNIT_RESULT'] |
| 27 | t = entry['__REALTIME_TIMESTAMP'] |
| 28 | except KeyError as e: |
| 29 | print(f'Exception: {type(e)}: {e}') |
| 30 | continue |
| 31 | print(f'{hostname} ({machine}): {unit} made a boo-boo: {result}') |
| 32 | sanitized_hostname = ''.join((x if x.isalnum() or x in ('-', '_', '.') else '_'+hex(ord(x))[2:]+'_') for x in hostname) |
| 33 | output_filename = output_directory / ('crash-' + sanitized_hostname + '-' + _compact_uuid(uuid.uuid4()) + '.journal') |
| 34 | reader = ('journalctl', |
| 35 | '-D', remote_directory, |
| 36 | # Python formats UUIDs with dashes, and journalctl doesn't accept that |
| 37 | '_MACHINE_ID=' + _compact_uuid(machine), |
| 38 | '_BOOT_ID=' + _compact_uuid(bootid), |
| 39 | '--since', '-1m', |
| 40 | '-o', 'export') |
| 41 | writer = ('/lib/systemd/systemd-journal-remote', |
| 42 | '-o', output_filename, |
| 43 | '--split-mode=none', |
| 44 | '-') |
| 45 | reader_proc = subprocess.Popen(reader, stdout=subprocess.PIPE) |
| 46 | writer_proc = subprocess.Popen(writer, stdin=reader_proc.stdout) |
| 47 | reader_proc.wait() |
| 48 | writer_proc.wait() |
| 49 | print(f' -> wrote to {output_filename}') |
| 50 | subprocess.Popen(('journalctl', '--file', output_filename, '-p4', '-o', 'cat'), |
| 51 | stdout=open(str(output_filename) + '.txt', 'w')).wait() |
| 52 | |
| 53 | if __name__ == '__main__': |
| 54 | main(sys.argv[1], Path(sys.argv[2])) |