]> git.wh0rd.org - home.git/blob - .bin/gentoo-check-services
gentoo-check-services: handle deleted files/libs automatically
[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 ))
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:]))