Как загружать deb-пакеты многопоточно с помощью metalink (скрипты и инструкция) 1
Рецепт был опубликован 7 апреля 2017 года в 16:30, а менялся 10 февраля 2020 года в 03:32.
Постоянная ссылка: http://www.nixp.ru/recipes/69.html
Входные данные: система Ubuntu Linux с установленной качалкой aria2 и настроенная на использование зеркала репозитория от Яндекса. Несмотря на то, что с mirror.yandex.ru загрузка происходит быстрее, чем со многих других зеркал, она всё ещё не так быстра, как позволяет подключение. Поэтому задача — качать пакеты на максимальной скорости.
Apt-p2p зависит от числа участников и в моей ситуации не помог, поэтому выбранное решение — многопоточная загрузка из нескольких источников с помощью создаваемого на ходу metalink-файла.
Шаблон, по которому скриптами будет создаваться файл загрузки (/root/opt/smpl.metalink):
<?xml version="1.0" encoding="UTF-8" ?> <metalink version="3.0" generator="Metalink Editor version 0.4.1" xmlns="http://www.metalinker.org/"> <files> <file name="forfilename"> <resources> <url type="http" preference="100">received-link</url> <url type="http" preference="110">one-more-link1</url> <url type="http" preference="120">one-more-link2</url> <url type="http" preference="130">one-more-link3</url> <url type="http" preference="140">one-more-link4</url> </resources> </file> </files> </metalink>
Скрипт на Python для загрузки и установки обновлений (/root/opt/apt-mt-upd.py):
import os, subprocess, time subprocess.call('apt-get update', shell=True) getlink = 'apt-get upgrade -dqq --print-uris && apt-get dist-upgrade -dqq --print-uris ' rawlist = os.popen(getlink)
while True: line = rawlist.readline() link = (line.split(' ')[0]).replace('\'', '') filename = (link.split('/')[-1]).replace('\'', '') if 'http' in line: #print(filename) inmetalink = open('/root/opt/smpl.metalink') tmpmetalink = inmetalink.read() tmpmetalink = tmpmetalink.replace('forfilename', filename) tmpmetalink = tmpmetalink.replace('received-link', link) tmpmetalink = tmpmetalink.replace('one-more-link1', (link.replace('yandex.ru', 'corbina.net'))) tmpmetalink = tmpmetalink.replace('one-more-link2', (link.replace('yandex.ru', 'timeweb.ru'))) tmpmetalink = tmpmetalink.replace('one-more-link3', (link.replace('yandex.ru', 'rol.ru'))) tmpmetalink = tmpmetalink.replace('one-more-link4', (link.replace('mirror.yandex.ru', 'ru.archive.ubuntu.com'))) outmetalink = open('/var/cache/apt/archives/getdeb.metalink', 'w') outmetalink.write(tmpmetalink) outmetalink.close() subprocess.call('aria2c -d /var/cache/apt/archives --max-connection-per-server=12 --min-split-size=1M -s 12 /var/cache/apt/archives/getdeb.metalink &', shell=True) time.sleep(1.5) else: break
while True: time.sleep(1) if list(os.popen('pidof aria2c')) == []: break
subprocess.call('apt-get -y upgrade && apt-get -y dist-upgrade', shell=True)
(Как видно из скрипта, для загрузки используются дополнительные российские зеркала репозиториев Ubuntu, подставляемые в шаблон на места one-more-linkX.)
Скрипт на Python, скачивающий пакеты без их установки, т.е. выполняющий apt-get install -d [download-only] (/root/opt/apt-mt-get.py):
import os, sys, subprocess, time subprocess.call('apt-get update', shell=True) getlink = 'apt-get install -dqq --print-uris ' + sys.argv[1] rawlist = os.popen(getlink) while True: line = rawlist.readline() link = (line.split(' ')[0]).replace('\'', '') filename = (link.split('/')[-1]).replace('\'', '') if 'http' in line: #print(filename) inmetalink = open('/root/opt/smpl.metalink') tmpmetalink = inmetalink.read() tmpmetalink = tmpmetalink.replace('forfilename', filename) tmpmetalink = tmpmetalink.replace('received-link', link) tmpmetalink = tmpmetalink.replace('one-more-link1', (link.replace('yandex.ru', 'corbina.net'))) tmpmetalink = tmpmetalink.replace('one-more-link2', (link.replace('yandex.ru', 'timeweb.ru'))) tmpmetalink = tmpmetalink.replace('one-more-link3', (link.replace('yandex.ru', 'rol.ru'))) tmpmetalink = tmpmetalink.replace('one-more-link4', (link.replace('mirror.yandex.ru', 'ru.archive.ubuntu.com'))) outmetalink = open('/var/cache/apt/archives/getdeb.metalink', 'w') outmetalink.write(tmpmetalink) outmetalink.close() subprocess.call('aria2c -d /var/cache/apt/archives --max-connection-per-server=12 --min-split-size=1M -s 12 /var/cache/apt/archives/getdeb.metalink &', shell=True) time.sleep(1) else: break while True: time.sleep(1) if list(os.popen('pidof aria2c')) == []: break
Как всё это использовать?
Обновление:
$ python3 /root/opt/apt-mt-upd.py
Загрузка пакета (на примере nexuiz-music):
$ python3 /root/opt/apt-mt-get.py nexuiz-music
- Из той же серии:
- Как установить пакеты в Debian/Ubuntu Linux, игнорируя вопросы конфигурации?
- Очистка Linux-системы Debian/Ubuntu от файлов, оставшихся после удаления пакетов
- Как отключить автоматическое обновление списка пакетов в Ubuntu Linux?
Последние комментарии
- OlegL, 17 декабря в 15:00 → Перекличка 21
- REDkiy, 8 июня 2023 года в 9:09 → Как «замокать» файл для юниттеста в Python? 2
- fhunter, 29 ноября 2022 года в 2:09 → Проблема с NO_PUBKEY: как получить GPG-ключ и добавить его в базу apt? 6
- Иванн, 9 апреля 2022 года в 8:31 → Ассоциация РАСПО провела первое учредительное собрание 1
- Kiri11.ADV1, 7 марта 2021 года в 12:01 → Логи catalina.out в TomCat 9 в формате JSON 1