blob: 015027ad4b220da7de6cd56174bee73440a0d62d [file] [log] [blame]
#!/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)