]>
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', | |
5efa74ba | 80 | '/usr/bin/daisydog': 'daisydog', |
ff421541 MF |
81 | '/usr/bin/distccd': 'distccd', |
82 | '/usr/bin/monit': 'monit', | |
83 | '/usr/bin/stunnel': 'stunnel', | |
84 | '/usr/bin/tor': 'tor', | |
85 | '/usr/bin/transmission-daemon': 'transmission-daemon', | |
86 | '/usr/bin/mediatomb': 'mediatomb', | |
87 | '/lib/systemd/systemd-udevd': 'udev', | |
88 | '/usr/libexec/nrpe': 'nrpe', | |
89 | '/usr/libexec/postfix/master': 'postfix', | |
90 | 'denyhosts.py': 'denyhosts', | |
91 | 'dropbear': 'dropbear', | |
92 | 'galileo': 'galileo', | |
93 | 'tlsdated': 'tlsdated', | |
94 | } | |
95 | def auto_restart(svcs): | |
96 | kill = set() | |
97 | restart = set() | |
98 | for pid, svc in svcs.items(): | |
99 | if svc['cmdline'][0] == '/sbin/agetty': | |
100 | kill.add(pid) | |
101 | elif 'postgres:' in svc['cmdline'][0]: | |
102 | p = os.path.basename(glob.glob('/etc/runlevels/default/postgresql-*')[0]) | |
103 | restart.add(p) | |
104 | elif svc['cmdline'][0].startswith('metalog'): | |
105 | restart.add('metalog') | |
106 | else: | |
107 | prog = svc['cmdline'][0] | |
108 | if prog.startswith('/usr/bin/python'): | |
109 | prog = os.path.basename(svc['cmdline'][1]) | |
110 | ||
111 | init = SERVICES.get(prog) | |
112 | if init: | |
113 | restart.add(init) | |
114 | ||
115 | if kill or restart: | |
116 | for pid in kill: | |
117 | print('killing %s (%s)' % (pid, svcs[pid]['cmdline'][0])) | |
118 | os.kill(pid, signal.SIGTERM) | |
119 | for init in restart: | |
120 | print('restarting %s' % init) | |
121 | os.system('/etc/init.d/%s -q restart' % init) | |
122 | ||
123 | time.sleep(1) | |
124 | svcs = find_svcs() | |
125 | ||
126 | return svcs | |
127 | ||
128 | ||
129 | def summarize(svcs): | |
130 | print() | |
131 | sslh = False | |
132 | for pid in svcs.keys(): | |
133 | if svcs[pid]['cmdline'][0] == '/usr/sbin/sslh': | |
134 | del svcs[pid] | |
135 | sslh = True | |
136 | if sslh: | |
137 | print('sslh needs restart') | |
138 | ||
139 | print() | |
140 | for pid, svc in svcs.items(): | |
141 | print(pid, svc['cmdline']) | |
142 | print('\t%s' % '\n\t'.join(svc['old_paths'])) | |
143 | ||
144 | ||
145 | def get_parser(): | |
146 | parser = argparse.ArgumentParser(description=__doc__) | |
147 | return parser | |
148 | ||
149 | ||
150 | def main(argv): | |
151 | parser = get_parser() | |
152 | opts = parser.parse_args(argv) | |
153 | ||
154 | svcs = find_svcs() | |
155 | svcs = auto_restart(svcs) | |
156 | summarize(svcs) | |
157 | ||
158 | ||
159 | if __name__ == '__main__': | |
160 | exit(main(sys.argv[1:])) |