(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
따라 다르 므로 및 및 해당 종속성이 포함됩니다. 또한 에 따라 다르 므로 내 스크립트는 모든 비디오 드라이버를 추출합니다. 하지만 에 대한 종속성을 선언했기 때문에 자체 요구 사항을 충족하기를 원합니다.debconf
cdebconf
debconf
debconf
cdebconf
xserver-xorg
xserver-xorg-video-all | xorg-driver-video
xserver-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 프로그램을 만들 수 있지만 내 목적에는 쉘 스크립트로도 충분할 것입니다.