]> git.wh0rd.org Git - home.git/blob - .bin/gentoo-check-services
check-services: handle paths w/spaces
[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(' ', 5)
43                         # Handle paths with spaces.
44                         path = path.rsplit(' ', 2)[0]
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:]))