]> git.wh0rd.org - home.git/commitdiff
gentoo-check-services: handle deleted files/libs automatically
authorMike Frysinger <vapier@gentoo.org>
Thu, 18 Feb 2016 06:37:32 +0000 (01:37 -0500)
committerMike Frysinger <vapier@gentoo.org>
Thu, 18 Feb 2016 06:37:32 +0000 (01:37 -0500)
.bin/gentoo-check-services [new file with mode: 0755]

diff --git a/.bin/gentoo-check-services b/.bin/gentoo-check-services
new file mode 100755 (executable)
index 0000000..bff7b33
--- /dev/null
@@ -0,0 +1,157 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""Script for restarting services that refer to old/deleted libs."""
+
+from __future__ import print_function
+
+import argparse
+import glob
+import os
+import signal
+import sys
+import time
+
+
+# Set of paths that are "OK" and safe to ignore.
+IGNORE_PATHS = set((
+       '/dev/zero',
+       '/etc/ld.so.cache',
+))
+
+
+def find_svcs():
+       """Find all programs w/deleted paths."""
+       svcs = {}
+       for pid in os.listdir('/proc'):
+               try:
+                       pid_nr = int(pid)
+               except ValueError:
+                       continue
+
+               map = '/proc/%s/maps' % pid
+               if not os.path.exists(map):
+                       print('skipping %s' % pid)
+                       continue
+
+               old_paths = set()
+               for line in open(map):
+                       if not line.endswith(' (deleted)\n'):
+                               continue
+                       # b71c7000-b7307000 rw-s 00000000 00:04 17024337   /dev/zero (deleted)
+                       addr, perm, offset, dev, inode, path, _ = line.split()
+                       if (path == '/[aio]' or
+                           path.startswith('/SYSV') or
+                           path.startswith('/dev/shm/')):
+                               continue
+                       old_paths.add(path)
+
+               old_paths -= IGNORE_PATHS
+               if not old_paths:
+                       continue
+
+               cmdline = open('/proc/%s/cmdline' % pid).read().split('\0')
+               try:
+                       while True:
+                               cmdline.remove('')
+               except ValueError:
+                       pass
+               svcs[pid_nr] = {
+                       'cmdline': cmdline,
+                       'old_paths': old_paths,
+               }
+       return svcs
+
+
+# Mapping of known programs to their init.d scripts.
+SERVICES = {
+       '/usr/sbin/acpid': 'acpid',
+       '/usr/sbin/apache2': 'apache2',
+       '/usr/sbin/atd': 'atd',
+       '/usr/sbin/bacula-fd': 'bacula-fd',
+       '/usr/sbin/cron': 'vixie-cron',
+       '/usr/sbin/crond': 'dcron',
+       '/usr/sbin/snmpd': 'snmpd',
+       '/usr/sbin/sshd': 'sshd',
+       '/usr/sbin/syslog-ng': 'syslog-ng',
+       '/usr/sbin/xinetd': 'xinetd',
+       '/usr/bin/distccd': 'distccd',
+       '/usr/bin/monit': 'monit',
+       '/usr/bin/stunnel': 'stunnel',
+       '/usr/bin/tor': 'tor',
+       '/usr/bin/transmission-daemon': 'transmission-daemon',
+       '/usr/bin/mediatomb': 'mediatomb',
+       '/lib/systemd/systemd-udevd': 'udev',
+       '/usr/libexec/nrpe': 'nrpe',
+       '/usr/libexec/postfix/master': 'postfix',
+       'denyhosts.py': 'denyhosts',
+       'dropbear': 'dropbear',
+       'galileo': 'galileo',
+       'tlsdated': 'tlsdated',
+}
+def auto_restart(svcs):
+       kill = set()
+       restart = set()
+       for pid, svc in svcs.items():
+               if svc['cmdline'][0] == '/sbin/agetty':
+                       kill.add(pid)
+               elif 'postgres:' in svc['cmdline'][0]:
+                       p = os.path.basename(glob.glob('/etc/runlevels/default/postgresql-*')[0])
+                       restart.add(p)
+               elif svc['cmdline'][0].startswith('metalog'):
+                       restart.add('metalog')
+               else:
+                       prog = svc['cmdline'][0]
+                       if prog.startswith('/usr/bin/python'):
+                               prog = os.path.basename(svc['cmdline'][1])
+
+                       init = SERVICES.get(prog)
+                       if init:
+                               restart.add(init)
+
+       if kill or restart:
+               for pid in kill:
+                       print('killing %s (%s)' % (pid, svcs[pid]['cmdline'][0]))
+                       os.kill(pid, signal.SIGTERM)
+               for init in restart:
+                       print('restarting %s' % init)
+                       os.system('/etc/init.d/%s -q restart' % init)
+
+               time.sleep(1)
+               svcs = find_svcs()
+
+       return svcs
+
+
+def summarize(svcs):
+       print()
+       sslh = False
+       for pid in svcs.keys():
+               if svcs[pid]['cmdline'][0] == '/usr/sbin/sslh':
+                       del svcs[pid]
+                       sslh = True
+       if sslh:
+               print('sslh needs restart')
+
+       print()
+       for pid, svc in svcs.items():
+               print(pid, svc['cmdline'])
+               print('\t%s' % '\n\t'.join(svc['old_paths']))
+
+
+def get_parser():
+       parser = argparse.ArgumentParser(description=__doc__)
+       return parser
+
+
+def main(argv):
+       parser = get_parser()
+       opts = parser.parse_args(argv)
+
+       svcs = find_svcs()
+       svcs = auto_restart(svcs)
+       summarize(svcs)
+
+
+if __name__ == '__main__':
+       exit(main(sys.argv[1:]))