Как скопировать пакеты с машины онлайн на офлайновую машину

У меня есть машина, которая онлайн. Это имеет установку, в которой я нуждаюсь на машине, которая не онлайн. Идеально был бы тривиальный способ копировать/клонировать установленные пакеты.

Увы, я не нашел, что это было тривиально. Я попробовал несколько предлагаемых решений:

0
задан 13 April 2017 в 05:24

1 ответ

Я записал простой Python util для использования apt list --installed и apt download <pkg> для создания папки "кэша", я должен использовать с aptoncd. Это также обновит папку кэша, ничего не повторно загружая.

ИСПОЛЬЗОВАНИЕ: <cmd> <cache_dir> [optional_regex_pkgs_to_ignore|...]

  • cmd -> имя файла, где Вы сохраняете этот сценарий
  • cache dir -> папка для сохранения кэшируемого вывода в. Если это будет содержать существующий .debs, то они не будут повторно загружены. Хорошее местоположение /var/cache/apt/archive на ubuntu16.04 (если у Вас есть sudo),
  • pkgs_to_ignore -> разделенный пробелом список пакетов для игнорирования, в regex формате. Например, 'google.*' пропустит googleearth и googleearth-package. Отметьте ' по сравнению с " - это препятствует тому, чтобы удар расширился .* в regex.
    • Необходимый, потому что это apt подход не будет работать на редкую программу, установленную полностью снаружи apt, например, Google Earth для меня.

Надежда это помогает кому-то. Казался немного отличающимся, чем существующие (многочисленные) вопросы. Отметьте, это не пытается заново изобрести колесо диспетчера пакетов; это не заботится об обновлениях версии пакета, если имя неизменно. Если это имеет значение, просто укажите на него на другую папку кэша, и это повторно загрузит все.

 #!/usr/bin/python3

'''
program to make a flat folder of all packages your system uses:
    - pulls all installed packages: 
        -`apt list --installed` 
    - downloads any packages/.deb's that are not in your cache folder
        - `apt download <package>`

This was created to facilitate setting up / updating an off-line
machine based on an existing machine (presumably online) where you 
have the programs you need set up.

the easiest way to get the packages over to the offline machine is via
tool `aptoncd`  ("sudo apt install aptoncd"), which will make an iso of
your packages, and optionally auto-launch a CD writer.

--- USAGE ---
<cmd> <working_dir> [ignore-pkg-globs|...]
'''

import sys
from os import path
from glob import glob
import os
import subprocess
import re

NARGS=2
DEBUG=0

def get_all_installed_packages():
    print("==== asking apt for a list of all installed packaged ====")
    result = subprocess.run(["apt", "list", "--installed"],
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT,
                            universal_newlines=True)
    if not 0 == result.returncode:
        msg = "apt list call failed with " + str(result.returncode)
        print(msg)
        raise RuntimeError(msg)

    split_re = re.compile(r"(.*)/(.*)(\[.*\])")
    packages = []
    for line in result.stdout.split(os.linesep):
        contents = split_re.match(line)
        if contents:
            groups = [item.strip() for item in contents.groups()]
            if DEBUG:
                print("found pkg: <{0}>  -- {1}|{2}".format(*groups))
            packages.append(groups[0])
        else:
            print("IGNORING <" + line + ">:")

    if len(packages) < 20:
        msg = "ERROR: you only found <{0}> packages, this seems wrong!".format(len(packages))
        print(msg)
        raise RuntimeError(msg)

    print("==== found {0} installed packages! ====".format(len(packages)))

    return packages

def download_packages(pkg_list, ignore_pkgs):
    if not pkg_list:
        print(" ==== nothing to download! ====")
        return
    print("==== downloading the following (missing) packages: ====")
    print(" | ".join(pkg_list))

    for pkg in pkg_list:
        if DEBUG:
            print("processing package <{0}>".format(pkg))
        ignore = 0
        for pattern in ignore_pkgs:
            if pattern.match(pkg):
                if DEBUG:
                    print("matched <{0}> to ignore pattern <{1}>".format(
                           pkg, pattern.pattern))
                ignore += 1

        if ignore:
            print("---- ignoring {0} {1} ----".format(pkg, ignore))
        else:
            print("---- downloading {0} ----".format(pkg))
            result = subprocess.run(["apt", "download", pkg],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT,
                                universal_newlines=True)
            if 0 != result.returncode:
                msg = "ERROR: run apt download failed with <{0}>. "
                msg += "output=\n{1}\n------\n\n".format(
                    result.returncode, result.stdout)
                raise RuntimeError(msg)

    print("==== DONE DOWNLOADING ====")

def main():
    if len(sys.argv) < NARGS:
        print(__doc__)
        msg = "ERROR, requires >= {0} args!".format(NARGS-1)
        print(msg)
        sys.exit(1)

    print("args=" + ";".join(sys.argv))

    ignore_pkgs_re = [re.compile(x) for x in sys.argv[2:]]
    package_dir = path.abspath(path.normpath(sys.argv[1]))

    if not path.isdir(package_dir):
        msg = "ERROR: path <{0}> is not a dir!".format(package_dir)
        print(msg)
        raise ValueError(msg)

    save_cwd = os.getcwd()
    try:
        os.chdir(package_dir)
        existing_debs = glob("*deb")
        for deb in existing_debs:
            if DEBUG > 1:
                print("found deb = " + deb)
            pass

        installed_packages = get_all_installed_packages()

        to_download = []
        for pkg in installed_packages:
            matching_deb = [x for x in existing_debs if x.startswith(pkg)]
            if matching_deb:
                if DEBUG:
                    print("found existing match for <{0}> with <{1}>".format(
                          pkg, "|".join(matching_deb)))
            else:
                if DEBUG:
                    print("no existing cache deb found for pkg <" + pkg + ">")
                to_download.append(pkg)

        download_packages(to_download, ignore_pkgs_re)

    finally:
        os.chdir(save_cwd)

if __name__ == "__main__":
    print("running as main")
    main()
2
ответ дан 7 November 2019 в 07:00

Другие вопросы по тегам:

Похожие вопросы: