安装多个deb文件,同时尊重它们的依赖关系

为了支持多个.deb文件的离线安装 ,我正在使用:

 sudo dpkg -i dependencies/*.deb 

我注意到有些软件包因为安装顺序而无法使用此方法

例如,当我安装mariadb-server-5.5及其依赖项时会发生这种情况:

这些是文件

这是错误

如何在尊重其依赖项的同时安装*.deb文件?

  • 我试图避免建立一个本地回购,因为它更难维护。
  • 作为一种解决方法,我运行命令dpkg -i *.deb两次。

您可以尝试使用-R并安装选项:

 sudo dpkg -R --install dependencies/ 

-R递归处理匹配在特定目录及其所有子目录中找到的模式* .deb的所有常规文件

拓扑排序(通过脚本)

命令dpkg -i packages/*.deb 是有问题的 – 没有正确地遵守应该安装的订单包(即使你提供了所有必需的包)。

自定义脚本来统治它们

假设您的debian发行版安装了python (我的是ubuntu 14.04 LTS并附带python27

除了离线.deb packages目录,提供一个脚本;

  • 提取元数据和拓扑对所有候选包进行排序
  • 使用dpkg -i以正确的顺序安装已排序的软件包

例如,执行此命令可安装所有预先收集的脱机程序包

 sudo python install.py 
  • 您的目录结构应如下所示

    在此处输入图像描述


install.py

 #!/usr/bin/env python import os import re import subprocess import logging import sys rootLogger = logging.getLogger() rootLogger.setLevel(logging.INFO) consoleHandler = logging.StreamHandler(sys.stdout) consoleHandler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")) rootLogger.addHandler(consoleHandler) SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) class TopologicalSort(object): def __init__(self, dependency_map): self._dependency_map = dependency_map self._already_processed = set() def _get_dependencies(self, item, root=None): if not root: root = item elif root == item: logging.warn("circular dependency detected in '{}'".format(item)) raise StopIteration() dependencies = self._dependency_map.get(item, []) for dependency in dependencies: if dependency in self._already_processed: continue self._already_processed.add(dependency) for sub_dependency in self._get_dependencies(dependency, root=root): yield sub_dependency yield dependency def sort(self): # Reduction, connect all nodes to a dummy node and re-calculate special_package_id = 'topological-sort-special-node' self._dependency_map[special_package_id] = self._dependency_map.keys() sorted_dependencies = self._get_dependencies(special_package_id) sorted_dependencies = list(sorted_dependencies) del self._dependency_map[special_package_id] # Remove "noise" dependencies (only referenced, not declared) sorted_dependencies = filter(lambda x: x in self._dependency_map, sorted_dependencies) return sorted_dependencies class DebianPackage(object): def __init__(self, file_path): metadata = subprocess.check_output('dpkg -I {}'.format(file_path), shell=True) metadata = metadata.replace('\n ', '\n') self._metadata = metadata self.id = self._get('Package') self.dependencies = list(self._get_dependencies()) self.file_path = file_path def _get_dependencies(self): dependencies = self._get('Depends') + ',' + self._get('Pre-Depends') dependencies = re.split(r',|\|', dependencies) dependencies = map(lambda x: re.sub(r'\(.*\)|:any', '', x).strip(), dependencies) dependencies = filter(lambda x: x, dependencies) dependencies = set(dependencies) for dependency in dependencies: yield dependency def _get(self, key): search = re.search(r'\n{key}:(.*)\n[AZ]'.format(key=key), self._metadata) return search.group(1).strip() if search else '' def sort_debian_packages(directory_path): file_names = os.listdir(directory_path) debian_packages = {} dependency_map = {} for file_name in file_names: file_path = os.path.join(directory_path, file_name) if not os.path.isfile(file_path): continue debian_package = DebianPackage(file_path) debian_packages[debian_package.id] = debian_package dependency_map[debian_package.id] = debian_package.dependencies sorted_dependencies = TopologicalSort(dependency_map).sort() sorted_dependencies = map(lambda package_id: debian_packages[package_id].file_path, sorted_dependencies) return sorted_dependencies def main(): # ------------------ # Sort the packages using topological sort packages_dir_path = os.path.join(SCRIPT_DIR, 'packages') logging.info('sorting packages in "{}" using topological sort ...'.format(packages_dir_path)) sorted_packages = sort_debian_packages(packages_dir_path) # ------------------ # Install the packages in the sorted order for index, package_file_path in enumerate(sorted_packages): command = 'dpkg -i {}'.format(package_file_path) logging.info('executing "{}" ...'.format(command)) subprocess.check_call(command, shell=True) if __name__ == '__main__': if os.geteuid() != 0: logging.error('must be run as root') sys.exit(1) try: main() except: logging.error('failed to install packages', exc_info=True) sys.exit(1)