kmmbvnr (kmmbvnr) wrote,
kmmbvnr
kmmbvnr

Categories:

Linux: Apt friend

UPDATE Тулза лежащая тут сейчас не совсем совместима с Ubuntu Edgy. Но тем не мение 3,4 человека в месяц ее скачивают. Я давно уже все починил и успешно продолжаю ей пользоваться, но мне все лень выложить новую версию. Если она вам действительно необходима - напишите комментарий или на мыло kmmbvnr _at_ inbox.ru.
Уфф довел до удобноваримого вида, одну скриптину, не стыдно даже расшарить.

Нараспространял я на свою голову халявную убунту, теперь встала проблема:

Приходит ко мне однажды друг, говорит - "О а чем это ты таким прикольным видео смортришь, дай мне".

Да действительно, теоретически ничего не мешает скопировать deb файл на флешку, да только вот загвоздка с зависимостями. Банальный mplayer тянет, ой много чего. Ну ладно один раз можно поковыряться в deb файле и вытащить что ему там надо, но криво это криво.

Да, да если на той машине есть хороший интернет, если на ней прописанны нужные репозитории, то проблема отпадает, хотя неприятный осадок остается, все равно еще раз качать, некрасиво.

Итак задача: Есть машина А с ubuntu на борту на которую мы бы хотели установить некоторые пакеты. Есть машина Б на которой эти пакеты уже имеются в наличии либо на этой машине канал в инет гораздо толше/дешевле/ваще халявный. Связь между машинами осуществляется самым демократичным способом - винтонетом, ну или с помощью флеш брелка. Требуется - собрать пакеты и недостающие зависимости в одной папке.

Варианты решения которые имеются в наличии:
 1) apt-get --print-uris
     1a) debget
 2) немного магии со  status файлом
 3) мой вариант - apt-dist


1) Самый простой и гибкий способ получить все необходимые пакеты - это сэмулировать их установку на исходной машине, посмотреть что требуется и потом просто напросто скачать это на машине 2. Для этого машина 1 должна иметь хоть какой-нибудь выход в интернет.

На машине 1 настраиваем sources.list, коннектимся к инету и выполняем apt-get update. Этой командой мы получаем списки пакетов находящихся в удаленных репозитариях. Теперь можно воспользоваться synaptic, aptitude или даже dselect для нахождения имен пакетов с требуемой вам функциональностью. Вместо того, чтобы устанавливать пакеты с помощью этих програм выполняем команду apt-get -qq --print-uris install имя_пакета_1 имя_пакета_2 и т.д. Опция --print-uris заставляет apt-get вместо того, чтобы скачивать и устанавливать пакеты просто напечатать url их местонахождения. А опция -qq выключает весь лишний вывод на экран. Копируем эти url в файл и идем на машину 2.

На машине 2 мы можем скачать пакеты из только что полученного файла выполнив команды:
cat наш_файл | awk 'print "wget -O " $2 " " $1}' > wget-script
sh -x ./wget-script
Первой командой мы создаем скрипт файл содержащий последовательность вызовов консольного downloader'a wget для скачивания каждого из пакетов. Второй командой мы запускаем этот скрипт на выполнение.

Основным минусом первого варианта является то, что пакеты, вне зависимости от наличия их в локальном репозитарии, будут скачаны заново. При наличии в сети/на локальной машине кешируешего deb пакеты прокси (apt-cacher или apt-proxy) некоторыми дополнительными ухишрениями с url можно заставить wget качать через него, но есть способ проще:

1а) Пакете debian-goodies среди прочего, предоставляет команду debget - скачивающую deb файл пользуясь локальной базой apt-get. С помощью его без проблем можно реализовать скачивание пакетов с локальных зеркал.

Минусами debget является отсутствие возможности указать требуемую версию пакета,требование прав root'a, и ошибки возникающие при попытке скачать deb с cdrom'a. Ключ к решению этих проблем описан во втором способе

2) С машины 1 забираем файл /var/lib/dpkg/status содержащий информацию об установленных пакетах. Этот файл единственное что нам нужно чтобы создать на машине 2 конфигурацию, для apt неотличимую от машины 1. Создание собственной конфигурации заодно делает ненужным права записи в /var/cache/apt, а значит права root'a нам не потребуются.

Первым делом в некотором каталоге, например /tmp/dist создаем следующую структуру папок:
/tmp/dist/
    archives/
        partial/
    lists/
        partial/
    status
    sources.list
    apt.conf
Где файл status - это тот самый файл с машины 1, файл sources.list должен содержать список репозитариев откуда вы хотите брать пакеты (можно просто скопировать /etc/apt/sources.list).

A файл apt.conf заполните следующим содержанием
APT {
    Architecture "i386"; //Используйте здесь название архитектуры машины 1 (скорее всего у вас  это i386 или x64)
    Get::Download-Only "true" //На машине 2 мы будем только скачивать пакеты
};
Dir {
   //Местоположение файлов с информацией об установленых пакетах
    State "/tmp/dist";
    State::status "status";

    //Папка для сохранения  deb файлов
    Cache::archives "/tmp/dist/archives";
    Cache "/tmp/dist"

   //Местоположение sources.list
   Etc "/tmp/dist"
}


Не забудьте изменить /tmp/dist на путь к вашему каталогу с конфигурацией. Как выяснилось опытным путем при указании папок в файле apt.conf можно использовать относительные пути везде кроме параметра Cache::archives

Запускаем:
export APT_CONFIG="/tmp/dist/apt.conf"
apt-get update
apt-get install имя_пакета


Т.к. В файле apt.conf опция APT::Get::Download-Only установленна в true, установка происходить не будет, но необходимые пакеты будут скачены. Но скачиваться будут только пакеты не из локальных репозитариев, из локальных репозитариев apt в принципе ничего не скачивает а сразу использует пакеты с данного места. Cd-rom'ы и снапшоты нна жестких дисках опять оказались не у дел.

Тут самое время вспомнить что apt отвечает только за скачивание нужных версий пакетов, а распаковывает и конфигурирует пакеты в debian-based дистрибутивах команда dpkg. Именно к ней и обращается apt-get при установке пакета. Сразу вырисовывется план действий - выключаем опцию APT::Get::Download-Only, тогда apt произведет попытку установки пакетов, но если вместо оригинального dpkg подставить скрипт обертку вокруг команды cp(copy) то пакеты будут не установленны а просто скопированны в нужное место. Это собственно и есть ядро способа 3.

3) Общим минусом всех выше перечисленных способов, является необходимоть каких-либо предварителльных действий на машине 1. Хотя обычно необходимость передать пакеты случается скорее случайно. О машине 1 как правило известно только что за дистрибутив на ней установлен, и что у ее владельца есть диски официального релиза этого дистрибутива. В принципе информации вполне достатчно, чтобы сформировать и скинуть на флешку все недостающие пакеты и их зависимости. Ну а если пара тройка из них окажутся уже установленными к этому времени на машине, ничего страшного. Первым делом сформируем status файл псевдо машины на которой как бы установленны все пакеты с официиальных cd/dvd. Т.к. cd/dvd потенциально могут содержать конфликтующие между собой пакеты, информацию о возможных конфликтах мы в статус файл записывать не будем, тогда apt будет считать что все нормально. А при попытке доустановить новый пакет, будут скачаны и установленны только те пакеты, которых нет на официальных дисках.

Вобшем, все эти рутинные действия я раз и навсегда реализовал в маленькой скриптине. Кого интересуют детали - рекомендую посмотреть на исходники(28кб) Как пользоваться скриптом, я специально не рассказываю, ибо ЛЮБОЙ скрипт полученный из странных мест (какой-то левый блог, какой-то халявный хостинг) НЕОБХОДИМО ПРОСМАТРИВАТЬ ГЛАЗАМИ. Мало ли что.

Результат мне нравиться. Никаких предварительных шаманских танцев, на безсофтовом компьютере, этот компьтер может быть вообще не подключен к инету, и чисто теоретически он может быть любой debian-based системой.

В правах рута на компьютере доноре нет необходимости.

P.S. NO WARRANTY P.P.S Big thanks to Jason Gunthorpe <jgg@debian.org> author of the APT Offline HOWTO.
Tags: linux
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 7 comments