2012/2/23 Javier Fernández-Sanguino Peña <j...@computer.org>: > On Wed, Feb 22, 2012 at 06:33:19PM +1100, Marcus Furlong wrote: >> If rpm support would be acceptable, I'd be happy to re-work the above >> patch so that it checks for the existence of "dpkg-query" and/or "rpm" >> and proceeds accordingly. > > I'm open to supporting rpm in checkrestart but to do so it would be best to > separate the dpkg and rpm calls into different functions and call one (or the > other) based not on the existance of the dpkg-query or rpm binaries > themselves (you can install the rpm software in Debian) but on wether you are > running in an rpm or deb-based distribution.
We have debian installations that have rpm installed (due to hardware RAID software that IBM distributes only as rpms). The attached patch checks for the existence of both dpkg-query and rpm. If it finds either it runs the corresponding checks. On our systems, this is the correct thing to do, as it finds both deb-based packages and rpm-based packages that require restarts. If either rpm or dpkg-query is not found, those codepaths are not executed. Tested on lenny, squeeze, opensuse, centos/sl/redhat 5/6. Regards, Marcus. -- Marcus Furlong
--- checkrestart.orig 2012-02-29 13:37:30.788710631 +1100 +++ checkrestart 2012-03-05 17:28:40.875381912 +1100 @@ -114,6 +114,11 @@ # TODO - This does not work yet: # toRestart = psdelcheck() + global dpkgQueryBin, rpmBin + + dpkgQueryBin = find_cmd('dpkg-query') + rpmBin = find_cmd('rpm') + toRestart = lsofcheck() print "Found %d processes using old versions of upgraded files" % len(toRestart) @@ -138,33 +143,13 @@ process.listDeleted() packages = {} - diverted = None - dpkgQuery = ["dpkg-query", "--search"] + programs.keys() - dpkgProc = subprocess.Popen(dpkgQuery, stdout=subprocess.PIPE, stderr=None, - env = lc_all_c_env) - for line in dpkgProc.stdout.readlines(): - if line.startswith('local diversion'): - continue + + if dpkgQueryBin != 1: + deb_packages(programs, packages) - m = re.match('^diversion by (\S+) (from|to): (.*)$', line) - if m: - if m.group(2) == 'from': - diverted = m.group(3) - continue - if not diverted: - raise Exception('Weird error while handling diversion') - packagename, program = m.group(1), diverted - else: - packagename, program = line[:-1].split(': ') - if program == diverted: - # dpkg prints a summary line after the diversion, name both - # packages of the diversion, so ignore this line - # mutt-patched, mutt: /usr/bin/mutt - continue - - packages.setdefault(packagename,Package(packagename)) - packages[packagename].processes.extend(programs[program]) - + if rpmBin != 1: + rpm_packages(programs, packages) + print "(%d distinct packages)" % len(packages) if len(packages) == 0: @@ -172,18 +157,31 @@ print "(please read checkrestart(1))" sys.exit(0) + for package in packages.values(): + output = '' if package == 'util-linux': continue - dpkgQuery = ["dpkg-query", "--listfiles", package.name] - dpkgProc = subprocess.Popen(dpkgQuery, stdout=subprocess.PIPE, stderr=None, + + if dpkgQueryBin != 1: + dpkgQuery = [dpkgQueryBin, "--listfiles", package.name] + dpkgProc = subprocess.Popen(dpkgQuery, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + env = lc_all_c_env) + for line in dpkgProc.stdout.readlines(): + output = output + "%s\n" % line + + if rpmBin != 1: + rpmQuery = [rpmBin, "-q", "-l", package.name] + rpmProc = subprocess.Popen(rpmQuery, stdout=subprocess.PIPE, stderr=None, env = lc_all_c_env) - for line in dpkgProc.stdout.readlines(): - path = line[:-1] - if path.startswith('/etc/init.d/'): - if path.endswith('.sh'): + for line in rpmProc.stdout.readlines(): + output = output + "%s \n" % line + + for line in output.splitlines(): + if line.startswith('/etc/init.d/') or line.startswith('/etc/rc.d/init.d/'): + if line.endswith('.sh'): continue - package.initscripts.add(path) + package.initscripts.add(line) # Alternatively, find init.d scripts that match the process name if len(package.initscripts) == 0: for process in package.processes: @@ -265,6 +263,7 @@ def isdeletedFile (f): global lc_all_c_env + global dpkgQueryBin, rpmBin if allFiles: return 1 @@ -284,7 +283,7 @@ if f.startswith('/run/'): return 0 # Or about files under /drm - if f.startswith('/drm/'): + if f.startswith('/drm'): return 0 # Or about files under /var/tmp if f.startswith('/var/tmp/'): @@ -318,15 +317,28 @@ # a proper filename file_name = re.sub(r'\(.*\)','', f) file_name = re.sub(r'\s+$','', file_name) - dpkgQuery = ["dpkg-query", "--search", file_name] - dpkgProc = subprocess.Popen(dpkgQuery, stdout=subprocess.PIPE, stderr=None, - env = lc_all_c_env) - for line in dpkgProc.stdout.readlines(): - if line.endswith(f): - file_in_package = True - break + if dpkgQueryBin != 1: + dpkgQuery = [dpkgQueryBin, "--search", file_name] + dpkgProc = subprocess.Popen(dpkgQuery, stdout=subprocess.PIPE, stderr=None, + env = lc_all_c_env) + for line in dpkgProc.stdout.readlines(): + if line.endswith(file_name): + file_in_package = True + break + if rpmBin != 1: + output = '' + rpmQuery = [rpmBin, "-q", "-f", "--queryformat=%{NAME}", file_name] + rpmProc = subprocess.Popen(rpmQuery, stdout=subprocess.PIPE, stderr=None, + env = lc_all_c_env) + for line in rpmProc.stdout.readlines(): + output = output + "%s: %s\n" % (line, file_name) + + for line in output.splitlines(): + if line.endswith(file_name): + file_in_package = True + break if not file_in_package: - return 0 + return 0 # TODO: it should only care about library files (i.e. /lib, /usr/lib and the like) # build that check with a regexp to exclude others @@ -386,6 +398,53 @@ return process +def deb_packages(programs, packages): + global dpkgQueryBin + diverted = None + dpkgQuery = [dpkgQueryBin, "--search"] + programs.keys() + dpkgProc = subprocess.Popen(dpkgQuery, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + env = lc_all_c_env) + for line in dpkgProc.stdout.readlines(): + if line.startswith('local diversion'): + continue + + m = re.match('^diversion by (\S+) (from|to): (.*)$', line) + if m: + if m.group(2) == 'from': + diverted = m.group(3) + continue + if not diverted: + raise Exception('Weird error while handling diversion') + packagename, program = m.group(1), diverted + else: + packagename, program = line[:-1].split(': ') + if program == diverted: + # dpkg prints a summary line after the diversion, name both + # packages of the diversion, so ignore this line + # mutt-patched, mutt: /usr/bin/mutt + continue + + packages.setdefault(packagename,Package(packagename)) + packages[packagename].processes.extend(programs[program]) + + +def rpm_packages(programs, packages): + global rpmBin + output = '' + for key in programs.keys(): + rpmQuery = [rpmBin, "-q", "-f", "--queryformat=%{NAME}", key] + rpmProc = subprocess.Popen(rpmQuery, stdout=subprocess.PIPE, stderr=None, + env = lc_all_c_env) + for line in rpmProc.stdout.readlines(): + if not line.endswith('is not owned by any package\n'): + output = output + "%s: %s\n" % (line, key) + + for line in output.splitlines(): + packagename, program = line.split(': ') + packages.setdefault(packagename,Package(packagename)) + packages[packagename].processes.extend(programs[program]) + + class SysProcess: re_name = re.compile('Name:\t(.*)$') re_uids = re.compile('Uid:\t(\d+)\t(\d+)\t(\d+)\t(\d+)$') @@ -447,7 +506,7 @@ newusr = os.path.join(os.path.dirname('/usr'), newusr) f = re.sub('^/usr',newusr, f) # print "Changing usr to " + newusr + " result:" +f; # Debugging - return re.sub('( \(deleted\)|.dpkg-new).*$','',f) + return re.sub('( \(deleted\)|.dpkg-new|\;|.#prelink#).*$','',f) def listDeleted(self): listfiles = []