65 | 65 |
return 1
|
66 | 66 |
|
67 | 67 |
def usage():
|
68 | |
sys.stderr.write('usage: checkrestart [-vhpa] [ -b blacklist_file ] [ -i package_name ] [ -e pid ]\n')
|
|
68 |
sys.stderr.write('usage: checkrestart [-vhpam] [ -b blacklist_file ] [ -i package_name ] [ -e pid ]\n')
|
69 | 69 |
|
70 | 70 |
def main():
|
71 | 71 |
global lc_all_c_env, file_query_check
|
|
84 | 84 |
|
85 | 85 |
# Process options
|
86 | 86 |
try:
|
87 | |
opts, args = getopt.getopt(sys.argv[1:], "hvpab:i:ne:", ["help", "verbose", "packages", "all", "blacklist", "ignore", "nolsof", "excludepid"])
|
|
87 |
opts, args = getopt.getopt(sys.argv[1:], "hvpamb:i:ne:t", ["help", "verbose", "packages", "all", "machine", "blacklist", "ignore", "nolsof", "excludepid", "terse"])
|
88 | 88 |
except getopt.GetoptError as err:
|
89 | 89 |
# print help information and exit:
|
90 | 90 |
print(err) # will print something like "option -x not recognized"
|
|
98 | 98 |
onlyPackageFiles = False
|
99 | 99 |
# Look for any deleted file
|
100 | 100 |
allFiles = False
|
|
101 |
# Generate terse output, disabled by default
|
|
102 |
terseOutput = False
|
|
103 |
# Generate machine parsable output, disabled by default
|
|
104 |
machineOutput = False
|
101 | 105 |
|
102 | 106 |
for o, a in opts:
|
103 | 107 |
if o in ("-v", "--verbose"):
|
|
112 | 116 |
onlyPackageFiles = False
|
113 | 117 |
elif o in ("-e", "--excludepid"):
|
114 | 118 |
excludepidlist.append(a)
|
|
119 |
elif o in ("-m", "--machine"):
|
|
120 |
machineOutput = True
|
115 | 121 |
elif o in ("-b", "--blacklist"):
|
116 | 122 |
blacklistFiles.append(a)
|
117 | 123 |
onlyPackageFiles = False
|
|
119 | 125 |
ignorelist.append(a)
|
120 | 126 |
elif o in ("-n", "--nolsof"):
|
121 | 127 |
useLsof = False
|
|
128 |
elif o in ("-t", "--terse"):
|
|
129 |
terseOutput = True
|
122 | 130 |
else:
|
123 | 131 |
assert False, "unhandled option"
|
124 | 132 |
|
|
149 | 157 |
else:
|
150 | 158 |
toRestart = lsoffilescheck(blacklist = blacklist)
|
151 | 159 |
|
152 | |
|
153 | |
print("Found %d processes using old versions of upgraded files" % len(toRestart))
|
|
160 |
if terseOutput:
|
|
161 |
# Terse output and exit
|
|
162 |
# Use Nagios exit codes: 0 OK, 1 warning, 2 critical, 3 unknown
|
|
163 |
# we only care for 0 or 1
|
|
164 |
if len(toRestart):
|
|
165 |
print("%d processes using old versions of upgraded files" % len(toRestart))
|
|
166 |
sys.exit(1)
|
|
167 |
# Exit with no error if there is nothing to restart
|
|
168 |
print("No processes found using old versions of upgraded files")
|
|
169 |
sys.exit(0)
|
|
170 |
|
|
171 |
if not machineOutput:
|
|
172 |
print("Found %d processes using old versions of upgraded files" % len(toRestart))
|
|
173 |
else:
|
|
174 |
print("PROCESSES: %d" % len(toRestart))
|
154 | 175 |
|
155 | 176 |
if len(toRestart) == 0:
|
156 | 177 |
sys.exit(0)
|
|
160 | 181 |
programs.setdefault(process.program, [])
|
161 | 182 |
programs[process.program].append(process)
|
162 | 183 |
|
163 | |
if len(programs) == 1:
|
164 | |
print("(%d distinct program)" % len(programs))
|
|
184 |
if not machineOutput:
|
|
185 |
if len(programs) == 1:
|
|
186 |
print("(%d distinct program)" % len(programs))
|
|
187 |
else:
|
|
188 |
print("(%d distinct programs)" % len(programs))
|
165 | 189 |
else:
|
166 | |
print("(%d distinct programs)" % len(programs))
|
|
190 |
print("PROGRAMS: %d" % len(programs))
|
|
191 |
|
167 | 192 |
|
168 | 193 |
#services Verbose information
|
169 | 194 |
if verbose:
|
170 | 195 |
for process in toRestart:
|
171 | |
print("[DEBUG] Process %s (PID: %d) " % (process.program, process.pid))
|
172 | |
process.listDeleted()
|
|
196 |
if not machineOutput:
|
|
197 |
print("[DEBUG] Process %s (PID: %d) " % (process.program, process.pid))
|
|
198 |
process.listDeleted()
|
|
199 |
else:
|
|
200 |
process.listDeletedMachine()
|
173 | 201 |
|
174 | 202 |
packages = {}
|
175 | 203 |
diverted = None
|
|
228 | 256 |
except KeyError:
|
229 | 257 |
continue
|
230 | 258 |
|
231 | |
print("(%d distinct packages)" % len(packages))
|
|
259 |
if not machineOutput:
|
|
260 |
print("(%d distinct packages)" % len(packages))
|
|
261 |
else:
|
|
262 |
print("PACKAGES: %d" % len(packages))
|
|
263 |
|
232 | 264 |
|
233 | 265 |
if len(packages) == 0:
|
234 | |
print("No packages seem to need to be restarted.")
|
235 | |
print("(please read checkrestart(1))")
|
|
266 |
if not machineOutput:
|
|
267 |
print("No packages seem to need to be restarted.")
|
|
268 |
print("(please read checkrestart(1))")
|
236 | 269 |
sys.exit(0)
|
237 | 270 |
|
238 | 271 |
for package in list(packages.values()):
|
|
287 | 320 |
nonrestartable.append(package)
|
288 | 321 |
|
289 | 322 |
if len(restartable) > 0:
|
290 | |
print()
|
291 | |
print("Of these, %d seem to contain systemd service definitions or init scripts which can be used to restart them." % len(restartable))
|
292 | |
# TODO - consider putting this in a --verbose option
|
293 | |
print("The following packages seem to have definitions that could be used\nto restart their services:")
|
294 | |
for package in restartable:
|
295 | |
print(package.name + ':')
|
296 | |
for process in package.processes:
|
297 | |
print("\t%s\t%s" % (process.pid,process.program))
|
298 | |
|
299 | |
if len(restartServiceCommands)>0:
|
|
323 |
if not machineOutput:
|
300 | 324 |
print()
|
301 | |
print("These are the systemd services:")
|
302 | |
print('\n'.join(restartServiceCommands))
|
303 | |
print()
|
304 | |
|
305 | |
if len(restartInitCommands)>0:
|
306 | |
print("These are the initd scripts:")
|
307 | |
print('\n'.join(restartInitCommands))
|
308 | |
print()
|
|
325 |
print("Of these, %d seem to contain systemd service definitions or init scripts which can be used to restart them." % len(restartable))
|
|
326 |
# TODO - consider putting this in a --verbose option
|
|
327 |
print("The following packages seem to have definitions that could be used\nto restart their services:")
|
|
328 |
for package in restartable:
|
|
329 |
print(package.name + ':')
|
|
330 |
for process in package.processes:
|
|
331 |
print("\t%s\t%s" % (process.pid,process.program))
|
|
332 |
|
|
333 |
if len(restartServiceCommands)>0:
|
|
334 |
print()
|
|
335 |
print("These are the systemd services:")
|
|
336 |
print('\n'.join(restartServiceCommands))
|
|
337 |
print()
|
|
338 |
|
|
339 |
if len(restartInitCommands)>0:
|
|
340 |
print("These are the initd scripts:")
|
|
341 |
print('\n'.join(restartInitCommands))
|
|
342 |
print()
|
|
343 |
else:
|
|
344 |
for package in restartable:
|
|
345 |
for process in package.processes:
|
|
346 |
print('SERVICE:%s,%s,%s' % (package.name, process.pid,process.program))
|
309 | 347 |
|
310 | 348 |
if len(nonrestartable) == 0:
|
311 | 349 |
sys.exit(0)
|
312 | 350 |
|
313 | 351 |
# TODO - consider putting this in a --verbose option
|
314 | |
print("These processes (%d) do not seem to have an associated init script to restart them:" %len(nonrestartable))
|
|
352 |
if not machineOutput:
|
|
353 |
print("These processes (%d) do not seem to have an associated init script to restart them:" %len(nonrestartable))
|
315 | 354 |
for package in nonrestartable:
|
316 | |
print(package.name + ':')
|
317 | |
for process in package.processes:
|
318 | |
print("\t%s\t%s" % (process.pid,process.program))
|
|
355 |
if not machineOutput:
|
|
356 |
print(package.name + ':')
|
|
357 |
for process in package.processes:
|
|
358 |
print("\t%s\t%s" % (process.pid,process.program))
|
|
359 |
else:
|
|
360 |
for process in package.processes:
|
|
361 |
print('OTHER:%s,%s,%s' % (package.name,process.pid,process.program))
|
|
362 |
|
319 | 363 |
|
320 | 364 |
def lsoffilescheck(blacklist = None):
|
321 | 365 |
# Use LSOF to extract the list of deleted files
|
|
707 | 751 |
# print "Changing usr to " + newusr + " result:" +f; # Debugging
|
708 | 752 |
return re.sub('( \(deleted\)|.dpkg-new).*$','',f)
|
709 | 753 |
|
710 | |
def listDeleted(self):
|
|
754 |
def listDeletedHelper(self):
|
711 | 755 |
listfiles = []
|
712 | 756 |
listdescriptors = []
|
713 | 757 |
for f in self.files:
|
714 | 758 |
if isdeletedFile(f):
|
715 | 759 |
listfiles.append(f)
|
716 | |
if listfiles != []:
|
717 | |
print("List of deleted files in use:")
|
718 | |
for file in listfiles:
|
719 | |
print("\t" + file)
|
|
760 |
return listfiles
|
|
761 |
def listDeleted(self):
|
|
762 |
listfiles = self.listDeletedHelper()
|
|
763 |
if listfiles != []:
|
|
764 |
print "List of deleted files in use:"
|
|
765 |
for file in listfiles:
|
|
766 |
print "\t" + file
|
|
767 |
def listDeletedMachine(self):
|
|
768 |
listfiles = self.listDeletedHelper()
|
|
769 |
for file in listfiles:
|
|
770 |
print 'file\t%s\t%s\t%s' % (self.pid, self.program, file)
|
|
771 |
|
720 | 772 |
|
721 | 773 |
# Check if a process needs to be restarted, previously we would
|
722 | 774 |
# just check if it used libraries named '.dpkg-new' since that's
|