Provide machine readable output based on patch provided by Simon Ruderich
Javier Fernandez-Sanguino
6 years ago
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:", ["help", "verbose", "packages", "all", "machine", "blacklist", "ignore", "nolsof", "excludepid"]) | |
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 machine parsable output | |
102 | machineOutput = False | |
101 | 103 | |
102 | 104 | for o, a in opts: |
103 | 105 | if o in ("-v", "--verbose"): |
112 | 114 | onlyPackageFiles = False |
113 | 115 | elif o in ("-e", "--excludepid"): |
114 | 116 | excludepidlist.append(a) |
117 | elif o in ("-m", "--machine"): | |
118 | machineOutput = True | |
115 | 119 | elif o in ("-b", "--blacklist"): |
116 | 120 | blacklistFiles.append(a) |
117 | 121 | onlyPackageFiles = False |
150 | 154 | toRestart = lsoffilescheck(blacklist = blacklist) |
151 | 155 | |
152 | 156 | |
153 | print("Found %d processes using old versions of upgraded files" % len(toRestart)) | |
157 | if not machineOutput: | |
158 | print("Found %d processes using old versions of upgraded files" % len(toRestart)) | |
159 | else: | |
160 | print("PROCESSES: %d" % len(toRestart)) | |
154 | 161 | |
155 | 162 | if len(toRestart) == 0: |
156 | 163 | sys.exit(0) |
160 | 167 | programs.setdefault(process.program, []) |
161 | 168 | programs[process.program].append(process) |
162 | 169 | |
163 | if len(programs) == 1: | |
164 | print("(%d distinct program)" % len(programs)) | |
170 | if not machineOutput: | |
171 | if len(programs) == 1: | |
172 | print("(%d distinct program)" % len(programs)) | |
173 | else: | |
174 | print("(%d distinct programs)" % len(programs)) | |
165 | 175 | else: |
166 | print("(%d distinct programs)" % len(programs)) | |
176 | print("PROGRAMS: %d" % len(programs)) | |
177 | ||
167 | 178 | |
168 | 179 | #services Verbose information |
169 | 180 | if verbose: |
170 | 181 | for process in toRestart: |
171 | print("[DEBUG] Process %s (PID: %d) " % (process.program, process.pid)) | |
172 | process.listDeleted() | |
182 | if not machineOutput: | |
183 | print("[DEBUG] Process %s (PID: %d) " % (process.program, process.pid)) | |
184 | process.listDeleted() | |
185 | else: | |
186 | process.listDeletedMachine() | |
173 | 187 | |
174 | 188 | packages = {} |
175 | 189 | diverted = None |
176 | 190 | |
177 | 191 | dpkgQuery = ["dpkg-query", "--search"] + list(programs.keys()) |
178 | if verbose: | |
192 | if verbose and not machineOutput: | |
179 | 193 | print("[DEBUG] Running: %s" % ' '.join(dpkgQuery)) |
180 | 194 | dpkgProc = subprocess.Popen(dpkgQuery, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, |
181 | 195 | env = lc_all_c_env) |
228 | 242 | except KeyError: |
229 | 243 | continue |
230 | 244 | |
231 | print("(%d distinct packages)" % len(packages)) | |
245 | if not machineOutput: | |
246 | print("(%d distinct packages)" % len(packages)) | |
247 | else: | |
248 | print("PACKAGES: %d" % len(packages)) | |
249 | ||
232 | 250 | |
233 | 251 | if len(packages) == 0: |
234 | print("No packages seem to need to be restarted.") | |
235 | print("(please read checkrestart(1))") | |
252 | if not machineOutput: | |
253 | print("No packages seem to need to be restarted.") | |
254 | print("(please read checkrestart(1))") | |
236 | 255 | sys.exit(0) |
237 | 256 | |
238 | 257 | for package in list(packages.values()): |
287 | 306 | nonrestartable.append(package) |
288 | 307 | |
289 | 308 | 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: | |
309 | if not machineOutput: | |
300 | 310 | 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() | |
311 | print("Of these, %d seem to contain systemd service definitions or init scripts which can be used to restart them." % len(restartable)) | |
312 | # TODO - consider putting this in a --verbose option | |
313 | print("The following packages seem to have definitions that could be used\nto restart their services:") | |
314 | for package in restartable: | |
315 | print(package.name + ':') | |
316 | for process in package.processes: | |
317 | print("\t%s\t%s" % (process.pid,process.program)) | |
318 | ||
319 | if len(restartServiceCommands)>0: | |
320 | print() | |
321 | print("These are the systemd services:") | |
322 | print('\n'.join(restartServiceCommands)) | |
323 | print() | |
324 | ||
325 | if len(restartInitCommands)>0: | |
326 | print("These are the initd scripts:") | |
327 | print('\n'.join(restartInitCommands)) | |
328 | print() | |
309 | 329 | |
310 | 330 | if len(nonrestartable) == 0: |
311 | 331 | sys.exit(0) |
312 | 332 | |
313 | 333 | # 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)) | |
334 | if not machineOutput: | |
335 | print("These processes (%d) do not seem to have an associated init script to restart them:" %len(nonrestartable)) | |
315 | 336 | for package in nonrestartable: |
316 | print(package.name + ':') | |
317 | for process in package.processes: | |
318 | print("\t%s\t%s" % (process.pid,process.program)) | |
337 | if not machineOutput: | |
338 | print(package.name + ':') | |
339 | for process in package.processes: | |
340 | print("\t%s\t%s" % (process.pid,process.program)) | |
341 | else: | |
342 | for process in package.processes: | |
343 | print 'no-init\t%s\t%s\t%s' % (package.name,process.pid,process.program) | |
344 | ||
319 | 345 | |
320 | 346 | def lsoffilescheck(blacklist = None): |
321 | 347 | # Use LSOF to extract the list of deleted files |
705 | 731 | # print "Changing usr to " + newusr + " result:" +f; # Debugging |
706 | 732 | return re.sub('( \(deleted\)|.dpkg-new).*$','',f) |
707 | 733 | |
708 | def listDeleted(self): | |
734 | def listDeletedHelper(self): | |
709 | 735 | listfiles = [] |
710 | 736 | listdescriptors = [] |
711 | 737 | for f in self.files: |
712 | 738 | if isdeletedFile(f): |
713 | 739 | listfiles.append(f) |
714 | if listfiles != []: | |
715 | print("List of deleted files in use:") | |
716 | for file in listfiles: | |
717 | print("\t" + file) | |
740 | return listfiles | |
741 | def listDeleted(self): | |
742 | listfiles = self.listDeletedHelper() | |
743 | if listfiles != []: | |
744 | print "List of deleted files in use:" | |
745 | for file in listfiles: | |
746 | print "\t" + file | |
747 | def listDeletedMachine(self): | |
748 | listfiles = self.listDeletedHelper() | |
749 | for file in listfiles: | |
750 | print 'file\t%s\t%s\t%s' % (self.pid, self.program, file) | |
751 | ||
718 | 752 | |
719 | 753 | # Check if a process needs to be restarted, previously we would |
720 | 754 | # just check if it used libraries named '.dpkg-new' since that's |