diff --git a/tools/analyze-dump-sort.py b/tools/analyze-dump-sort.py new file mode 100755 index 0000000000..015027ad4b --- /dev/null +++ b/tools/analyze-dump-sort.py @@ -0,0 +1,78 @@ +#!/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)