избавиться от случайно установленных пакетов

избавиться от случайно установленных пакетов

Кажется, я случайно добавил system76 ppa для Pop!_OS в свою установку Ubuntu 20.04. (Что действительно странно, так это то, что я этого не заметил...)

В то же время я удалил ppa и записи в списке репозиториев, которые смог найти. Система близка к тому, чтобы вернуться в нормальное состояние. Тем не менее, я думаю, что у меня остались некоторые остатки, по крайней мере, так я интерпретирую следующий вывод:

$ apt list --installed  | grep pop[0-9]

accountsservice/now 0.6.55-0ubuntu13.2pop0~1605745773~20.04~d9482b1 amd64 [installed,local]
gnome-settings-daemon-common/now 3.36.1-0ubuntu1pop0~1596026424~20.04~8296153 all [installed,local]
gnome-terminal-data/now 3.36.2-1ubuntu1~20.04pop0~1594780610~20.04~8048ed7 all [installed,local]
gnome-terminal/now 3.36.2-1ubuntu1~20.04pop0~1594780610~20.04~8048ed7 amd64 [installed,local]
...

Как мне теперь выяснить, к какому репозиторию они относятся, и как мне понизить эти пакеты до версии, которая содержится в текущих активных репозиториях?

Например, я вижу:

$ apt policy gnome-settings-daemon-common
gnome-settings-daemon-common:
  Installed: 3.36.1-0ubuntu1pop0~1596026424~20.04~8296153
  Candidate: 3.36.1-0ubuntu1pop0~1596026424~20.04~8296153
  Version table:
 *** 3.36.1-0ubuntu1pop0~1596026424~20.04~8296153 100
        100 /var/lib/dpkg/status
     3.36.1-0ubuntu1 500
        500 http://xx.archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages
        500 http://xx.archive.ubuntu.com/ubuntu focal-updates/main i386 Packages
     3.36.0-1ubuntu2 500
        500 http://xx.archive.ubuntu.com/ubuntu focal/main amd64 Packages
        500 http://xx.archive.ubuntu.com/ubuntu focal/main i386 Packages

И:

$ apt-cache madison  gnome-settings-daemon-common
gnome-settings-daemon-common | 3.36.1-0ubuntu1 | http://xx.archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages
gnome-settings-daemon-common | 3.36.1-0ubuntu1 | http://xx.archive.ubuntu.com/ubuntu focal-updates/main i386 Packages
gnome-settings-daemon-common | 3.36.0-1ubuntu2 | http://xx.archive.ubuntu.com/ubuntu focal/main amd64 Packages
gnome-settings-daemon-common | 3.36.0-1ubuntu2 | http://xx.archive.ubuntu.com/ubuntu focal/main i386 Packages
gnome-settings-daemon | 3.36.0-1ubuntu2 | http://xx.archive.ubuntu.com/ubuntu focal/main Sources
gnome-settings-daemon | 3.36.1-0ubuntu1 | http://xx.archive.ubuntu.com/ubuntu focal-updates/main Sources

Я интерпретирую это как указание на то, что установленная в данный момент версия не содержится в репозиториях.

Но как мне вернуть версию в репозитории? В идеале я хотел бы сделать это длявсепакеты...

ОБНОВЛЯТЬТеперь я вручную заменил все пакеты на те, которые мне нужны, используя apt-get install package=version. Это было большой головной болью, потому что мне приходилось искать нужную версию для apt policyкаждого из них, а иногда заменять целую кучу пакетов сразу, чтобы удовлетворить зависимости. Хотя моя проблема решена, я все еще очень заинтересован в том, как можно было бы сделать такую ​​очистку более эффективно.

решение1

После всей этой утомительной ручной работы по очистке я в конце концов написал скрипт на Python, который идентифицирует все пакеты, которых нет в активных репозиториях, или для которых установлены более новые версии, чем те, что есть в репозиториях.

Приведенный ниже код — это быстрое решение, и он не победит в конкурсе красоты, но мне он помог.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Identify all packages that are not in active repositories or for
which newer versions are installed.
"""

import re
import subprocess
from pprint import pprint


def get_packages():
    vers = subprocess.run("apt-show-versions", shell=True, capture_output=True)
    vers = vers.stdout.decode("utf-8").splitlines()
    vers = [y for y in (x.strip() for x in vers) if y]
    not_in_archive = {}
    newer_than_archive = {}
    others = {}
    for pkg in vers:
        p = [x.strip() for x in pkg.split(' ', 2)]
        name = p[0]
        vers = p[1]
        status = p[2] if len(p) == 3 else ''
        if vers == 'not' and status == 'installed':
            continue
        if status == 'uptodate':
            continue

        tmp = {name: {'vers': vers}}
        if status == 'installed: No available version in archive':
            not_in_archive.update(tmp)
        elif status == 'newer than version in archive':
            newer_than_archive.update(tmp)
        else:
            others.update(tmp)
            others[name][status] = status

    return not_in_archive, newer_than_archive, others


def get_version(pkg):
    vers = subprocess.run("apt policy {}".format(pkg),
                          shell=True, capture_output=True)
    vers = vers.stdout.decode("utf-8").splitlines()

    vt = re.compile(r'^ +version table:', re.IGNORECASE)
    stars = re.compile(r'^ \*\*\* *')

    res = []

    while True:
        line = vers.pop(0)
        if vt.match(line):
            break

    for i, line in enumerate(vers):
        if line[:8].strip():
            s = line[:5]
            v = line[5:].split(' ', 1)[0]
            installed = bool(stars.match(s))
        else:
            p, a = line[8:].split(' ', 1)
            res.append({'installed': installed,
                        'version': v,
                        'prio': p,
                        'archive': a})
    return res


if __name__ == '__main__':

    missing, newer, rest = get_packages()

    url = re.compile(r'^https?://', re.IGNORECASE)

    res = {}

    for p in newer:
        v = get_version(p)
        for x in v:
            if url.match(x['archive']):
                res[p] = x['version']
                break

    if missing:
        print("===== packages not in repositories =====")
        print(' '.join(p for p in missing))
        print()

    if rest:
        print("===== packages with other status =====")
        pprint(rest)
        print()

    if res:
        print("===== command to downgrade =====")
        print('sudo apt-get install {}'.format(
            ' '.join('{}={}'.format(p, v) for p, v in res.items())))

Например, после отключения PPA darktable и kicad я получаю

===== packages not in repositories =====
darktable-dbg:amd64 libpng12-0:amd64 zoom:amd64

===== command to downgrade =====
sudo apt-get install darktable:amd64=3.0.1-0ubuntu1 kicad:amd64=5.1.5+dfsg1-2build2 kicad-demos:all=5.1.5+dfsg1-2build2 kicad-doc-en:all=5.1.5+dfsg1-2build2 kicad-footprints:all=5.1.5-1 kicad-libraries:all=5.1.5+dfsg1-2build2 kicad-packages3d:all=5.1.5-1 kicad-symbols:all=5.1.5-1 kicad-templates:all=5.1.5-1

Последняя команда понизит версию установленных пакетов, а те, что указаны выше, придется удалить с помощью apt-get remove ....

(Я понимаю, что ppa-purge — это способ, если речь идет только об удалении ppa, а все остальное в системе «чисто», но это не всегда так)

Связанный контент