| #!/usr/bin/python |
| # SPDX-License-Identifier: LGPL-2.1-or-later |
| |
| """ |
| A helper to compare 'systemd-analyze dump' outputs. |
| |
| systemd-analyze dump >/var/tmp/dump1 |
| (reboot) |
| tools/analyze-dump-sort.py /var/tmp/dump1 → this does a diff from dump1 to current |
| |
| systemd-analyze dump >/var/tmp/dump2 |
| tools/analyze-dump-sort.py /var/tmp/{dump1,dump2} → this does a diff from dump1 to dump2 |
| """ |
| |
| import argparse |
| import tempfile |
| import subprocess |
| |
| def sort_dump(sourcefile, destfile=None): |
| if destfile is None: |
| destfile = tempfile.NamedTemporaryFile('wt') |
| |
| units = {} |
| unit = [] |
| |
| same = [] |
| |
| for line in sourcefile: |
| line = line.rstrip() |
| |
| header = line.split(':')[0] |
| if 'Timestamp' in header or 'Invocation ID' in header or 'PID' in header: |
| line = header + ': …' |
| |
| if line.startswith('->'): |
| if unit: |
| units[unit[0]] = unit |
| unit = [line] |
| elif line.startswith('\t'): |
| assert unit |
| |
| if same and same[0].startswith(header): |
| same.append(line) |
| else: |
| unit.extend(sorted(same, key=str.lower)) |
| same = [line] |
| else: |
| print(line, file=destfile) |
| |
| if unit: |
| units[unit[0]] = unit |
| |
| for unit in sorted(units.values()): |
| print('\n'.join(unit), file=destfile) |
| |
| destfile.flush() |
| return destfile |
| |
| def parse_args(): |
| p = argparse.ArgumentParser(description=__doc__) |
| p.add_argument('one') |
| p.add_argument('two', nargs='?') |
| p.add_argument('--user', action='store_true') |
| return p.parse_args() |
| |
| if __name__ == '__main__': |
| opts = parse_args() |
| |
| one = sort_dump(open(opts.one)) |
| if opts.two: |
| two = sort_dump(open(opts.two)) |
| else: |
| user = ['--user'] if opts.user else [] |
| two = subprocess.run(['systemd-analyze', 'dump', *user], |
| capture_output=True, text=True, check=True) |
| two = sort_dump(two.stdout.splitlines()) |
| with subprocess.Popen(['diff', '-U10', one.name, two.name], stdout=subprocess.PIPE) as diff: |
| subprocess.Popen(['less'], stdin=diff.stdout) |