다양한 대상 시스템에 대한 패키지 종속성을 어떻게 해결합니까?

다양한 대상 시스템에 대한 패키지 종속성을 어떻게 해결합니까?

(TL;DR: 초기 상태와 필수 패키지 목록이 주어지면 설치할 최소 패키지 세트를 어떻게 결정합니까?)

배포 이미지에 액세스할 수 없는 시스템을 위한 Ubuntu 설치 프로그램 ISO를 만들고 있습니다. 이는 임베디드 장치이며 기본 패키지와 일부 로컬로 빌드된 패키지만 필요합니다.게다가 모든 종속성. 예를 들어 우리는 Qt/Xcb를 사용하고 있기 때문에 libqt5*다양한 패키지를 도입해야 합니다.

현재 저는 설치 프로그램의 pool/extras 디렉토리에 무엇을 넣을지 결정하기 위해 무차별 대입 방법을 사용하고 있습니다. 먼저, debconf에 대한 답변에 언급된 패키지를 Seed로 사용한 d-i pkgsel/include후 다음 명령을 사용하여 재귀 종속성을 찾았습니다 bash.

# 1. Extract the dependencies from packages/*, removing version
#    conditions and changing separator to newline.
# 2. Find the recursive dependencies of all these packages using
#    package database, extracting Depends and PreDepends.
# 3. For each package we require:
#    a. if we find it in our cache, just copy it into the ISO (using
#       hard link for speed and space)
#    b. else, if we find it already in the ISO, do nothing
#    c. else, pass it through to step 4.
# 4. Search for matching packages in repositories that are not virtual
#    or foreign-architecture.
# 5. Download matching package files to the ISO.
(for i in "$TOP/packages"/*.deb; do dpkg-deb -f $i depends; done) | sed 's/([^()]*)//g;s/[|,]/\n/g'                                     \
  | xargs -r apt-cache --recurse --important depends | sed -re 's/^  (Pre)?Depends://;/[<|:]/d;s/^  *//;' | sort -u                     \
  | ( while read p;                                                                                                                     \
    do test $(find "$TOP/extras" -name "${p}_*.deb" -exec mv '{}' "$REMASTER_HOME"/remaster-iso/pool/extras \; -printf "true" -quit)    \
      || test $(find "$REMASTER_HOME"/remaster-iso/pool/{main,extras} -name "${p}_*.deb" -printf "true" -quit)                          \
      || echo $p;                                                                                                                       \
    done; )                                                                                                                             \
  | uniq | sed -r 's/[^ ]+/!~rforeign!~v^&$/' | xargs -r aptitude -q2 -F '%p' search                                                    \
  | (cd "$REMASTER_HOME"/remaster-iso/pool/extras; xargs -r apt-get download)

여기서는 $TOP/packages시드 패키지 디렉터리, $TOP/extras이전에 다운로드한 패키지의 캐시 $REMASTER_HOME"/remaster-iso및 압축이 풀린 설치 프로그램 ISO의 루트 디렉터리입니다.

apt-cache depends위의 접근 방식은 작동하지만 각 패키지에 대한 모든 대체 종속성이 보고되기 때문에 실제로 필요한 것보다 더 많은 것을 가져오는 경향이 있습니다 . 예를 들어 는 ; 제공 에 grub-pc따라 다르 므로 및 및 해당 종속성이 포함됩니다. 또한 에 따라 다르 므로 내 스크립트는 모든 비디오 드라이버를 추출합니다. 하지만 에 대한 종속성을 선언했기 때문에 자체 요구 사항을 충족하기를 원합니다.debconfcdebconfdebconfdebconfcdebconfxserver-xorgxserver-xorg-video-all | xorg-driver-videoxserver-xorg-video-fbdev

내가 원하는 것은 aptitude --download-only install ${MY_PACKAGES}대상 시스템에서 실행되는 것과 동일합니다. 그러나 물론 빌드 호스트에서 실행하면 대부분의 패키지가 이미 설치되어 있으므로 손실됩니다.

현재 시청 중python-apt라이브러리를 실행하고 있지만 실행 중인 호스트가 아닌 대상 시스템에 대해 초기화하는 예를 찾을 수 없습니다. 내가 복제할 수 있는 유사한 작업을 수행한 사람이 있습니까?

아니면 다른 가능한 방법이 있나요? 나는 원시적이고 최소한의 chroot를 생성하고 aptitude그 안에서 명령을 실행하는 것을 고려하고 있지만 이것이 유지 관리 부담이 되고 다른 사람들이 자신의 컴퓨터에 설정하기 어려울 것이라는 점이 걱정됩니다.

패키지를 업데이트할 때 필요한 종속성을 찾기 위해 이 솔루션(새로운 초기 상태 포함)을 사용할 수 있기를 바랍니다. 대상 시스템의 이동식 미디어에 대한 일관된 세트를 작성해야 하기 때문입니다(여전히 배포 이미지에 액세스할 수 없음). .

답변1

debootstrap디렉토리에 깨끗한 새 시스템을 설정하고, 를 사용하여 해당 디렉토리에서 원하는 작업을 수행 chroot하고, 거기에 있는 모든 것을 가져옵니다 chrootdir/var/cache/apt/archives/.

debootstrap두 번째 답변 후 편집: 방금 매뉴얼을 확인한 결과 원하는 작업의 대부분(전부는 아니지만)을 수행하는 데 사용할 수 있는 것 같습니다 . 아래에서 실행할 수 있으며 및 옵션이 fakeroot있고 다른 패키지도 추가할 수 있습니다. 종속성을 혼합하고 해결합니다.--download-only--print-debs--include

소스를 읽기 전에 두 가지 다른 소스 세트를 사용하는 것이 확실하지 않습니다. 그것도 지원하는 것 같습니다 :)

예를 들어:

% fakeroot /usr/sbin/debootstrap --variant=minbase --download-only --include=dnsutils wheezy /tmp/foo "http://ftp.us.debian.org/debian file:///local_packages_dir/"
[...]
I: Resolving dependencies of required packages...
I: Resolving dependencies of base packages...
I: Found additional required dependencies: [...]
I: Found additional base dependencies: [...]
[...]

약간의 오버헤드가 있습니다.

% du -sh /tmp/foo/var/cache/apt/archives/
40M     /tmp/foo/var/cache/apt/archives/
% du -sh /tmp/foo/
68M     /tmp/foo/

실제 다운로드는 apt-mirror와 같은 도구를 사용하여 최적화할 수 있으므로 매번 원격 위치에서 동일한 파일이 다운로드되지 않습니다.

답변2

이것은 bash대신 스크립트 이지만 python-apt내가 찾은 것은dpkg-offline비슷한 논리가 관련되어 있습니다. 나는 그것이 어떻게 작동하는지 조사하고 필요한 다운로드를 수행하기 위한 자체 스크립트를 성공적으로 만들었습니다. 루트가 아닌 일반 사용자로서 재현 가능합니다.

#!/bin/bash
set -e

die() {
    exec >&2
    printf '%s\n' "$@"
    exit 1
}

test "$UID" != "0" || die \
    "Do not run '$0' as root, because it will break your packages."

test -n "$1" || die \
    "Usage: $0 <package-dir> [package] ..." \
    "  package may be followed by _ - + &m etc; like 'aptitude install'" \
    "  local packages must be listed in package-dir/Packages.gz" \
    "  downloaded packages are saved to package-dir/ubuntu"

PACKAGE_DIR="$1"; shift

BASE_DIR=$(mktemp -d)
trap 'rm -r "$BASE_DIR"' EXIT

(
    cd $BASE_DIR

    # Skeleton directory structure
    mkdir -p \
        etc/apt/preferences.d \
        etc/apt/sources.list.d \
        var/cache/apt/archives \
        var/lib/apt/lists \
        var/lib/aptitude \
        var/lib/dpkg \
        var/log

    # Use GPG keys from host, and create empty dpkg status
    cp /etc/apt/trusted.gpg etc/apt
    touch var/lib/dpkg/status

    cat >etc/apt/sources.list <<-EOF
    # Locally-built packages
    deb file://$PACKAGE_DIR /

    # Upstream distribution to pillage
    deb http://gb.archive.ubuntu.com/ubuntu/ trusty main restricted universe
    EOF

    # Don't let user's ~/.aptitude/* influence anything
    export HOME="$BASE_DIR"
    APT_OPTIONS=(-q2 \
        -o "Apt::Architecture=amd64" \
        -o "Apt::Install-Recommends=0" \
        -o "Dir::Etc=$BASE_DIR/etc/apt" \
        -o "Dir::State=$BASE_DIR/var/cache/apt" \
        -o "Dir::Cache=$BASE_DIR/var/cache/apt" \
        -o "Dir::Cache::Archives=$BASE_DIR/var/cache/apt/archives" \
        -o "Dir::Log=$BASE_DIR/var/log" \
        -o "Dir::State::Lists=$BASE_DIR/var/lib/apt/lists" \
        -o "Dir::State::status=$BASE_DIR/var/lib/dpkg/status" \
        -o "DPkg::Options::--admindir=$BASE_DIR/var/lib/dpkg" \
        )

    APTITUDE="aptitude ${APT_OPTIONS[@]}"

    $APTITUDE update
    $APTITUDE --download-only -y --allow-untrusted install "$@"
)

# We now have all required package files download into cache; put them
# into output directory.
ln -t "$PACKAGE_DIR/ubuntu" -vf var/cache/apt/archives/*.deb

# Create updated package index
( cd "$PACKAGE_DIR" && dpkg-scanpackages -m . | gzip -c >Packages.gz )

아마도 이것을 사용하여 동일한 작업을 수행하는 Python 프로그램을 만들 수 있지만 내 목적에는 쉘 스크립트로도 충분할 것입니다.

관련 정보