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