From: Max Rembrov <Demimurych@mail.ru.>
Date: Mon, 17 Feb 2005 14:31:37 +0000 (UTC)
Subject: Добавление CD дисков с RPM но без индексных файлов через apt-cdrom
На OpenNet, по согласованию с автором статьи, публикуется переработанный вариант
документа http://www.netpeoples.ru/content.php?review.76
Что делать если apt-cdrom не хочет добавлять диск.
В статье, демонстрируется набор шагов в результате которых apt принимает
в свои репозитарии диски не только созданные для него, а и любые другие
с rpm пакетами. В статье есть ссылка на скрипт от автора, назначение
которого автоматизировать всю эту работу.
Описание принципов работы с APT выходит за рамки данной статьи,
подробнее см. документ http://www.linuxshare.ru/docs/distro/redhat/rh9/APT_RH809.html
Задача.
В apt есть утилита apt-cdrom, назначение которой добавлять в
репозитарии apt индексные файлы с CD, содержащих rpm пакеты, дабы
легко и просто, в случае если нужный пакет есть на CD, поставить его
оттуда. И опять же все наверняка в курсе что если CD создан без этих
индексных файлов, apt-cdrom сообщало, что таких файлов нет и
ничегошеньки добавлять не хотело. (А дистрибутивов созданных без
таких файлов множество - все RedHat-based например).
Решалась эта проблема двумя простыми способами - первый в ручную
переписать все свои CD и добавить туда индексные файлы, и второе -
просто создать репозитарий на жестком диске, куда и переписать пакеты
с CD. В силу моей бедности (как финансовой так и духовной) места на винте,
как и новых болванок, у меня нету, а потому я решил эту задачу другим
способом. И теперь apt принимает любые диски содержащие rpm пакеты.
Как это делается описано ниже.
Скрипт все делающий за меня.
Поздравляю Вас - такой скрипт есть. Проверялось все на apt версии
apt-0.5.15cnc6. Впрочем должно работать, в принципе, и на более ранних
версиях. Точнее даже так - работать будет везде где формат
sources.list совместим с данной версией.
- это apt пакет для третей федоры
http://ftp.freshrpms.net/pub/freshrpms/fedora/linux/3/apt/apt-0.5.15cnc6-1.1.fc3.fr.i386.rpm
- это apt для второй.
http://ftp.freshrpms.net/pub/freshrpms/fedora/linux/2/apt/apt-0.5.15cnc6-1.1.fc2.fr.i386.rpm
Стиль программирования у меня аховый - хотя небольшой бета тестинг,
на нескольких подопытных людях, не выявил серьезных проблем. Потому
пользуйтесь, а если найдете в себе силы поучить меня как можно было
сделать лучше - уж будьте любезны это сделать - я даже настаиваю.
Да - и если вдруг что то у Вас пошло не так - с подробностями
все ж таки ознакомиться придется. Ну и на всякий случай сделайте архивную
копию вашего /etc/apt/sources.list.
Скрипт можно скачать здесь
http://www.netpeoples.ru/files/downloads/aptfakecd.gz
Порядок действий вручную
Итак все пошагово.
Монтируем наш CD
[root@1CSERV apt]# mount /mnt/cdrom (Ну или /media/cdrom)
Определяемся с тем где у нас будет лежать кой-какая служебная
информация. (Я лично предпочел ее засунуть туда же где сам apt держит
свой кеш то есть /var/state/apt)
Создаем там директорию.
[root@1CSERV apt]# mkdir /var/state/apt/apt
Да - именно apt. Не знаю почему, некогда было разбираться, но apt уж
очень хочет чтобы репозитарии на CD лежали именно в папке apt - ну да
бог с ним.
Создаем в этой папке simlink именем RPMS.$name (где $name будет имя
репозитория - например Fedora_CD1) на CD где лежат rpm ки. То есть
если на примере той же fedora это так
Во первых все _ были преобразованы в %5f (Это же касается и пробелов -
их менять на %20)
Во вторых все / в названии файла были заменены на _
Зачем все это делает apt я могу только догадываться.
В третьих обратите внимание на то что было добавлено
.._.._.._.._(Зачем так и зачем столько станет ясно позднее. Хотя
наверняка шаманы уже стали догадываться)
Обратите внимание на два важных факта
Первый - кол-во ../../../../ должно четко совпадать с количеством
заданных ранее таких же краказяблов (см. пункт Перенесем
руками индексы в кеш apt:)
И второй - вообще все названия источника должно быть идентичным
кешевому файлу за исключением тех мутных преобразований / в _,
пробелов в %20 и т.д.
И последнее - необходимо добавить "ident key" вашего CD в APT
Делаем
[root@1CSERV apt]# apt-cdrom ident
Используется точка монтирования CD-ROM /mnt/cdrom/
Монтируется CD-ROM
Распознаётся.. [fcc8845cc52233baf7cbbb8c5fcff136-2]
Сохранённая метка: ''
Вот та последовательность в квадратных скобках и есть нужный нам ключ.
Аккуратненько переписываем его на бумажку
Переписали ?
Набираем теперь строчку в /var/state/apt/cdroms.list
Чтение списков пакетов... Завершено
Построение дерева зависимостей... Завершено
Следующие НОВЫЕ пакеты будут установлены: epiphany
0 будет обновлено, 1 новых установлено, 0 пакетов будет удалено и 0 не будет обновлено.
Необходимо получить 0B/1609kB архивов.
После распаковки потребуется дополнительно 4627kB дискового пространства.
Смена диска: Вставьте, пожалуйста, диск с меткой 'Fedora_CD1'
в устройство '/mnt/cdrom/' и нажмите .
Получено: 1 cdrom://Fedora_CD1 ../../../../../var/state/apt/apt/Fedora_CD1 epiphany 1.0.6-2 [1609kB]
Получено 1609kB за 12s (132kB/s).
Совершаем изменения...
Preparing... ########################################### [100%]
1:epiphany ########################################### [100%]
Done.
А что мне так и не объяснили что это за точечки ../../../../
Тому кто предпочитает не напрягаться поясню суть идеи.
Утилита apt-cdrom все что делает - это ищет по диску папочку apt,
берет оттуда индексы для репозитария, копирует их в кеш и добавляет в
сорц лист ссылку на папку откуда она взяла это все с CD. Более того
все пакеты должны лежать не просто в папочках а в папочках вида
RPMS.bla_bla_bla.
Нам необходимо решить было две задачи - первая это как то впихнуть ему
в кеш новые индексы нашего CD. И сделать так чтобы на
нашем CD появилась папка RPMS.bla_bla_bla (в тех же RedHat-ах папки с
RPM ками называются всегда RPMS. Понимаете не RPMS.bla_bla_bla, а
RPMS). RPMS.bla_bla_bla мы создали как сим-линк указывающий на RPMS на
CD. Поскольку касательно CD apt использует строки из сорцлиста таким
образом что /mnt/cdrom/ наш путь к пакету
то чтобы вернуться и попасть на наш сим линк - который лежит в
/var/state/apt/apt надо сделать /mnt/cdrom/../../var/state/apt/apt
Вот зачем эти точечки.
Наблюдательные спросят - а зачем делать ../../../../ если
достаточно было ../../ ?
А я отвечу, что хоть я и беден духом, но щедр душой потому мне точечек
не жалко.
Ну вот вобщем то и все.
Все эти операции (и некоторые другие полезности) делает мой скрипт - и
точечки считает почти правильно.
Заключение
В перспективе сделать скрипт, который был бы врапером между
оригинальным apt-cdrom и моим монстром. В самого монстра добавить
опцию автосканирования. Нужно это мне затем чтобы из synaptic (фронт
енд для apt) можно было мышкой CD добавлять.
Благодарности
Большое спасибо всем тем людям которые поддерживали меня и наставляли
на пути к просветлению.
Виктор Вислобоков - за его статью о apt и synaptice которая
мне очень, в свое время, помогла.
Randy - бессменного бета тестера и главного редактора моих
изышлизмов.
bloody - за координацию моих действий и помощь.
#!/bin/sh
#
# $Id: apt-fake-cdrom,v 0.01 2005/02/04 22:48:37
#
# This script tries to add your non apt-based CDROM (RedHat like etc...) into apt repository
# http://www.netpeoples.ru/files/downloads/aptfakecd.gz
#
#
usage="
This buggy script tries to add your non apt-based CDROM (RedHat like etc...) into apt repository
v 0.01pre Alfa (C)opyright by Demimurych demimurych@mail.ru. 2005.
Options:n
--name Name for CD n
--aptstate Path to apt state directory. Default /var/state/apt
--data Path to folder where apt-fakecd puts our data. Default: data=aptstate/apt n
--path Path to folder on CDROM where are RPMS placedn
-h, --help Display this helpn
n
Examples:n
n
apt-fakecd --name=Fedora_CD2 --path=/mnt/cdrom/RedHat/RPMS/n
apt-fakecd --name=ASP_CD1 --path=/media/cdrom/ASPLinux/RPMS/n
n
"
# bloat is necessary for non-Conectiva distros, at least RH,
# because they use file dependencies with a non-predictable
# heuristic. So we can't strip-off paths that will probably
# never appear in dependencies.
if [ -z "$*" ]; then
echo -e "$usage" 1>&2
exit 1
fi
if [ "$UID" -ne 0 ]
then
echo "Need root "
exit 1
fi
bloat=""
name=
data=
path=
aptstate=
while test $# -gt 0 ; do
case "$1" in
-h | --help)
echo -e "$usage"
exit 0
;;
--name=*)
name=`echo $1 | sed 's/^--name=//'`
;;
--data=*)
data=`echo $1 | sed 's/^--data=//'`
;;
--path=*)
path=`echo $1 | sed 's/^--path=//'`
;;
--aptstate=*)
path=`echo $1 | sed 's/^--aptstate=//'`
;;
-*)
echo -e "$usage" 1>&2
exit 1
;;
*)
break
;;
esac
shift
done
echo -e "E[32mLet's rock ...."
tput sgr0
if [ ! -n "$aptstate" ]; then
#echo -n "aptstate not specified. Tryning default .... "
aptstate=/var/state/apt
if [ ! -d "$aptstate" ]; then
echo "error: invalid aptstate dir : " 1>&2
exit 1
fi
#echo -e 'E[32mOK'
#tput sgr0
fi
if [ ! -n "$data" ]; then
data=$aptstate
fi
if [ ! -n "$name" ]; then
echo "error: name must be specified "
echo -e "$usage" 1>&2
exit 1
fi
if [ ! -n "$path" ]; then
echo "error: path must be specified "
echo -e "$usage" 1>&2
exit 1
fi
if cat /etc/apt/sources.list|grep $name >/dev/null; then
echo -n "Name $name alrady in use. Rewrite (y/N)? "
read answer
case "$answer" in
[yY]) rm -f $OF
echo "Ok. Rewrite..."
;;
anekdot)
echo "Со слов менеджера - поломался компьютер. Пришел системный администратор"
echo "- закатил глаза, вознес руки к небу, побормотал что то себе под нос,"
echo "четыре раза крутанул кресло вокруг оси - пхнул ногой системный блок"
echo "- компьютер заработал."
echo "Со слов админа: Вызывают меня - прихожу вижу этот мудило так крутился"
echo "на кресле что наматал на него шнур питания. Матюгаясь раскрутил шнур"
echo "- запихнул системный блок подальше под стол - матюкаясь пошел курить"
exit 1
;;
*) exit 1
;;
esac
fi
if [ ! -d "$data" ]; then
echo "Creating directory apt in $aptstate"
mkdir $data
fi
if [ ! -d "$path" ]; then
echo "Wrong path: $path"
exit 1
fi
echo "The aptstate:"$aptstate
echo "The name is :"$name
echo "The data is :"$data
echo "The path is :"$path
echo -n "Try to "apt-cdrom ident" ...."
if ! apt-cdrom ident > /dev/null ;then
echo "Faile ;("
exit 1
fi
aptident=`apt-cdrom ident`
#отрежим все что справа от матюка
aptident=${aptident#*[}
#отрежем все что слева от матюка
aptident=${aptident%]*}
echo -e 'E[32mOK'
tput sgr0
rm $data/RPMS.$name >/dev/null 2>&1
echo -n "Try to create simlink $data/RPMS.$name on $path ...."
if ! ln -s $path $data/RPMS.$name ; then
echo "Failed :("
exit 1
fi
echo -e 'E[32mOK'
tput sgr0
datasplit=`echo $data | sed 's/_/%5f/g'` # convert _ character to %5f in path
datasplit=`echo $datasplit | sed 's///_/g'` # convert / character to _ in path
datasplit=`echo $datasplit | sed 's/ /%20/g'` # convert space character to %20 in path
namesplit=`echo $name | sed 's/_/%5f/g'` # convert _ character to %5f in name
namesplit=`echo $namesplit | sed 's/ /%20/g'` # convert space character to %20 in name
echo -n "Try to use genbasedir ...."
if ! genbasedir --progress --bloat --flat $data $name ; then
echo "failed :("
exit 1
fi
echo -e 'E[32mOK'
tput sgr0
echo -n "Moving hash files ..."
if ! mv $data/base/pkglist.$name $aptstate/lists/$namesplit_$backslstrip$datasplit_base_pkglist.$namesplit ; then
echo "Failed :("
exit 1
fi
if ! mv $data/base/release.$name $aptstate/lists/$namesplit_$backslstrip$datasplit_base_release.$namesplit ; then
echo "Failed :("
exit 1
fi
echo -e 'E[32mOK'
tput sgr0
if [ ! -f "$aptstate/cdroms.list" ]; then
touch $aptstate/cdroms.list
fi