]> git.wh0rd.org Git - home.git/blob - .bin/gentoo-check-services
ddnuke: add fdisk+prompt to startup, and rough ETA
[home.git] / .bin / gentoo-check-services
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 """Script for restarting services that refer to old/deleted libs."""
5
6 from __future__ import print_function
7
8 import argparse
9 import glob
10 import os
11 import signal
12 import sys
13 import time
14
15
16 # Set of paths that are "OK" and safe to ignore.
17 IGNORE_PATHS = set((
18         '/dev/zero',
19         '/etc/ld.so.cache',
20         '/usr/share/icons/Adwaita/icon-theme.cache',
21         '/usr/share/icons/gnome/icon-theme.cache',
22         '/usr/share/icons/hicolor/icon-theme.cache',
23         '/usr/share/mime/mime.cache',
24 ))
25
26
27 def find_svcs():
28         """Find all programs w/deleted paths."""
29         svcs = {}
30         for pid in os.listdir('/proc'):
31                 try:
32                         pid_nr = int(pid)
33                 except ValueError:
34                         continue
35
36                 map = '/proc/%s/maps' % pid
37                 if not os.path.exists(map):
38                         print('skipping %s' % pid)
39                         continue
40
41                 old_paths = set()
42                 for line in open(map):
43                         if not line.endswith(' (deleted)\n'):
44                                 continue
45                         # b71c7000-b7307000 rw-s 00000000 00:04 17024337   /dev/zero (deleted)
46                         addr, perm, offset, dev, inode, path = line.split(' ', 5)
47                         # Handle paths with spaces.
48                         path = path.lstrip().rsplit(' ', 2)[0]
49                         if (path == '/[aio]' or
50                             path.startswith('/memfd:') or
51                             path.startswith('/SYSV') or
52                             path.startswith('/dev/shm/') or
53                             path.startswith('/tmp/')):
54                                 continue
55                         old_paths.add(path)
56
57                 old_paths -= IGNORE_PATHS
58                 if not old_paths:
59                         continue
60
61                 cmdline = open('/proc/%s/cmdline' % pid).read().split('\0')
62                 try:
63                         while True:
64                                 cmdline.remove('')
65                 except ValueError:
66                         pass
67                 svcs[pid_nr] = {
68                         'cmdline': cmdline,
69                         'old_paths': old_paths,
70                 }
71         return svcs
72
73
74 # Mapping of known programs to their init.d scripts.
75 SERVICES = {
76         '/usr/sbin/acpid': 'acpid',
77         '/usr/sbin/apache2': 'apache2',
78         '/usr/sbin/atd': 'atd',
79         '/usr/sbin/bacula-fd': 'bacula-fd',
80         '/usr/sbin/cron': 'vixie-cron',
81         '/usr/sbin/crond': 'dcron',
82         '/usr/sbin/ntpd': 'ntpd',
83         '/usr/sbin/snmpd': 'snmpd',
84         '/usr/sbin/sshd': 'sshd',
85         '/usr/sbin/syslog-ng': 'syslog-ng',
86         '/usr/sbin/xinetd': 'xinetd',
87         '/usr/bin/daisydog': 'daisydog',
88         '/usr/bin/distccd': 'distccd',
89         '/usr/bin/monit': 'monit',
90         '/usr/bin/rsync': 'rsyncd',
91         '/usr/bin/stunnel': 'stunnel',
92         '/usr/bin/tor': 'tor',
93         '/usr/bin/transmission-daemon': 'transmission-daemon',
94         '/usr/bin/mediatomb': 'mediatomb',
95         '/lib/systemd/systemd-udevd': 'udev',
96         '/usr/libexec/nrpe': 'nrpe',
97         '//usr/libexec/postfix/master': 'postfix',
98         'denyhosts.py': 'denyhosts',
99         'dropbear': 'dropbear',
100         'galileo': 'galileo',
101         'tlsdated': 'tlsdated',
102 }
103 def auto_restart(opts, svcs):
104         kill = set()
105         restart = set()
106         for pid, svc in svcs.items():
107                 if svc['cmdline'][0] == '/sbin/agetty':
108                         kill.add(pid)
109                 elif 'postgres:' in svc['cmdline'][0]:
110                         p = os.path.basename(glob.glob('/etc/runlevels/default/postgresql-*')[0])
111                         restart.add(p)
112                 elif svc['cmdline'][0].startswith('metalog'):
113                         restart.add('metalog')
114                 else:
115                         prog = svc['cmdline'][0]
116                         if prog.startswith('/usr/bin/python'):
117                                 prog = os.path.basename(svc['cmdline'][1])
118
119                         init = SERVICES.get(prog)
120                         if init:
121                                 restart.add(init)
122
123         if kill or restart:
124                 for pid in kill:
125                         print('killing %s (%s)' % (pid, svcs[pid]['cmdline'][0]))
126                         if not opts.dryrun:
127                                 os.kill(pid, signal.SIGTERM)
128                 for init in restart:
129                         print('restarting %s' % init)
130                         if not opts.dryrun:
131                                 os.system('/etc/init.d/%s -q restart' % init)
132
133                 if not opts.dryrun:
134                         time.sleep(1)
135                         svcs = find_svcs()
136
137         return svcs
138
139
140 def summarize(svcs):
141         print()
142         sslh = False
143         for pid in svcs.keys():
144                 if svcs[pid]['cmdline'][0] == '/usr/sbin/sslh':
145                         del svcs[pid]
146                         sslh = True
147         if sslh:
148                 print('sslh needs restart')
149
150         print()
151         for pid, svc in svcs.items():
152                 print(pid, svc['cmdline'])
153                 print('\t%s' % '\n\t'.join(svc['old_paths']))
154
155
156 def get_parser():
157         parser = argparse.ArgumentParser(description=__doc__)
158         parser.add_argument('-n', '--dry-run', dest='dryrun', action='store_true',
159                             help='Show what would be restarted (and why)')
160         return parser
161
162
163 def main(argv):
164         parser = get_parser()
165         opts = parser.parse_args(argv)
166
167         svcs = find_svcs()
168         svcs = auto_restart(opts, svcs)
169         summarize(svcs)
170
171
172 if __name__ == '__main__':
173         exit(main(sys.argv[1:]))