]>
Commit | Line | Data |
---|---|---|
ff421541 MF |
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 | )) | |
21 | ||
22 | ||
23 | def find_svcs(): | |
24 | """Find all programs w/deleted paths.""" | |
25 | svcs = {} | |
26 | for pid in os.listdir('/proc'): | |
27 | try: | |
28 | pid_nr = int(pid) | |
29 | except ValueError: | |
30 | continue | |
31 | ||
32 | map = '/proc/%s/maps' % pid | |
33 | if not os.path.exists(map): | |
34 | print('skipping %s' % pid) | |
35 | continue | |
36 | ||
37 | old_paths = set() | |
38 | for line in open(map): | |
39 | if not line.endswith(' (deleted)\n'): | |
40 | continue | |
41 | # b71c7000-b7307000 rw-s 00000000 00:04 17024337 /dev/zero (deleted) | |
e04a292f MF |
42 | addr, perm, offset, dev, inode, path = line.split(' ', 5) |
43 | # Handle paths with spaces. | |
44 | path = path.rsplit(' ', 2)[0] | |
ff421541 MF |
45 | if (path == '/[aio]' or |
46 | path.startswith('/SYSV') or | |
47 | path.startswith('/dev/shm/')): | |
48 | continue | |
49 | old_paths.add(path) | |
50 | ||
51 | old_paths -= IGNORE_PATHS | |
52 | if not old_paths: | |
53 | continue | |
54 | ||
55 | cmdline = open('/proc/%s/cmdline' % pid).read().split('\0') | |
56 | try: | |
57 | while True: | |
58 | cmdline.remove('') | |
59 | except ValueError: | |
60 | pass | |
61 | svcs[pid_nr] = { | |
62 | 'cmdline': cmdline, | |
63 | 'old_paths': old_paths, | |
64 | } | |
65 | return svcs | |
66 | ||
67 | ||
68 | # Mapping of known programs to their init.d scripts. | |
69 | SERVICES = { | |
70 | '/usr/sbin/acpid': 'acpid', | |
71 | '/usr/sbin/apache2': 'apache2', | |
72 | '/usr/sbin/atd': 'atd', | |
73 | '/usr/sbin/bacula-fd': 'bacula-fd', | |
74 | '/usr/sbin/cron': 'vixie-cron', | |
75 | '/usr/sbin/crond': 'dcron', | |
76 | '/usr/sbin/snmpd': 'snmpd', | |
77 | '/usr/sbin/sshd': 'sshd', | |
78 | '/usr/sbin/syslog-ng': 'syslog-ng', | |
79 | '/usr/sbin/xinetd': 'xinetd', | |
80 | '/usr/bin/distccd': 'distccd', | |
81 | '/usr/bin/monit': 'monit', | |
82 | '/usr/bin/stunnel': 'stunnel', | |
83 | '/usr/bin/tor': 'tor', | |
84 | '/usr/bin/transmission-daemon': 'transmission-daemon', | |
85 | '/usr/bin/mediatomb': 'mediatomb', | |
86 | '/lib/systemd/systemd-udevd': 'udev', | |
87 | '/usr/libexec/nrpe': 'nrpe', | |
88 | '/usr/libexec/postfix/master': 'postfix', | |
89 | 'denyhosts.py': 'denyhosts', | |
90 | 'dropbear': 'dropbear', | |
91 | 'galileo': 'galileo', | |
92 | 'tlsdated': 'tlsdated', | |
93 | } | |
94 | def auto_restart(svcs): | |
95 | kill = set() | |
96 | restart = set() | |
97 | for pid, svc in svcs.items(): | |
98 | if svc['cmdline'][0] == '/sbin/agetty': | |
99 | kill.add(pid) | |
100 | elif 'postgres:' in svc['cmdline'][0]: | |
101 | p = os.path.basename(glob.glob('/etc/runlevels/default/postgresql-*')[0]) | |
102 | restart.add(p) | |
103 | elif svc['cmdline'][0].startswith('metalog'): | |
104 | restart.add('metalog') | |
105 | else: | |
106 | prog = svc['cmdline'][0] | |
107 | if prog.startswith('/usr/bin/python'): | |
108 | prog = os.path.basename(svc['cmdline'][1]) | |
109 | ||
110 | init = SERVICES.get(prog) | |
111 | if init: | |
112 | restart.add(init) | |
113 | ||
114 | if kill or restart: | |
115 | for pid in kill: | |
116 | print('killing %s (%s)' % (pid, svcs[pid]['cmdline'][0])) | |
117 | os.kill(pid, signal.SIGTERM) | |
118 | for init in restart: | |
119 | print('restarting %s' % init) | |
120 | os.system('/etc/init.d/%s -q restart' % init) | |
121 | ||
122 | time.sleep(1) | |
123 | svcs = find_svcs() | |
124 | ||
125 | return svcs | |
126 | ||
127 | ||
128 | def summarize(svcs): | |
129 | print() | |
130 | sslh = False | |
131 | for pid in svcs.keys(): | |
132 | if svcs[pid]['cmdline'][0] == '/usr/sbin/sslh': | |
133 | del svcs[pid] | |
134 | sslh = True | |
135 | if sslh: | |
136 | print('sslh needs restart') | |
137 | ||
138 | print() | |
139 | for pid, svc in svcs.items(): | |
140 | print(pid, svc['cmdline']) | |
141 | print('\t%s' % '\n\t'.join(svc['old_paths'])) | |
142 | ||
143 | ||
144 | def get_parser(): | |
145 | parser = argparse.ArgumentParser(description=__doc__) | |
146 | return parser | |
147 | ||
148 | ||
149 | def main(argv): | |
150 | parser = get_parser() | |
151 | opts = parser.parse_args(argv) | |
152 | ||
153 | svcs = find_svcs() | |
154 | svcs = auto_restart(svcs) | |
155 | summarize(svcs) | |
156 | ||
157 | ||
158 | if __name__ == '__main__': | |
159 | exit(main(sys.argv[1:])) |