さまざまなターゲットシステムのパッケージ依存関係をどのように解決しますか?

さまざまなターゲットシステムのパッケージ依存関係をどのように解決しますか?

(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/

debootstrap2回目の回答後の編集:今すぐマニュアルを確認した結果、必要な作業のほとんど(すべてではありません)を実行するために使用できるようです。以下で実行でき、オプションがfakerootあり、他のパッケージも追加できます。依存関係を混合して解決します。--download-only--print-debs--include

ソースを読む前に、2つの異なるソースセットを使用することは不明です。それもサポートしているようです:)

たとえば、

% 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プログラムを作成できますが、私の目的にはシェルスクリプトで十分です。

関連情報