Üst düzey manuel olarak kurulan paketleri bağımlılıkları olmadan listeleyin


12

Manuel aptolarak yüklenen paketleri göstermenin birçok yolu vardır , örneğin:

apt-mark showmanual

Ancak bazen bu çıktı çok fazladır. Örneğin, kullanıcı paketi manuel olarak yüklediyse foo:

apt-get install foo

... ve foobağlıydı barve bazdaha sonra, apt-mark showmanualçıkış alacaktı:

bar
baz
foo

Nasıl biz sadece üst düzey elle yüklenen paketler (listeleyebilirsiniz yani foo (bağımlılıkları olmadan) yani değil baz, ne bar)?


Aşağıdaki kod işe yarıyor gibi görünüyor, ancak birkaç yüz kez çağrı yapan GNU çok yavaş, (4 çekirdekli CPU ile üç saat):parallelapt-rdepends

apt-mark showmanual | 
tee /tmp/foo | 
parallel "apt-rdepends -f Depends,PreDepends,Suggests,Recommends {} |
          tail +2" 2> /dev/null | 
tr -s ' ' '\n' | 
grep -v '[():]' | 
sort -Vu | 
grep -wv -f - /tmp/foo

Hmm. Cevaplar ve OP kodu, hepsi çok farklı ve hangi yöntemin verilerinin en doğru olduğu konusunda biraz bulanıklaştığımdan biraz farklı veriler döndürüyorum. Belki de asgari bir test sisteminden başlayarak ve çıktının nasıl ve ne zaman değiştiğini görmek için her seferinde birkaç program ekleyerek bir anket cevabı gereklidir.
agc

Yanıtlar:


9

Bu, Python apt API'sı kullanılarak yapılabilir. Eğer gördüğünüz paketler apt-mark showmanualhalinde tam olanlardır apt.cache.Cache()kendisi için is_installedde geçerlidir ve is_auto_installedyanlıştır. Ancak, bağımlılıkları işlemek daha kolaydır:

#! /usr/bin/env python3

from apt import cache

manual = set(pkg for pkg in cache.Cache() if pkg.is_installed and not pkg.is_auto_installed)
depends = set(dep_pkg.name for pkg in manual for dep in pkg.installed.get_dependencies('PreDepends', 'Depends', 'Recommends') for dep_pkg in dep)

print('\n'.join(pkg.name for pkg in manual if pkg.name not in depends))

Bu bile orada görmeyi beklemediğim bazı paketleri listeler ( init, grep?!).


Kodum 3 saatlik kodumun bir üst kümesini çıktılar, ancak initve grep(belki de apt verileriniz bozuk?) Gibi sürprizler göstermiyor , ayrıca çok fazla kütüphane gösteriyor. OTOH, 3 saatlik kodum orada olması gereken birkaç öğeyi, yukarıdaki kodun yazdırdığı öğeleri özlüyorpython . Muhtemelen eksik öğeler yüklenmemiş apt.
agc

@agc muhtemelen bunu tekrarlamamıştım. Hafta sonundan sonra özyinelemeli bir seçenek deneyeceğim. Özyineleme ile bile, bunun tekrar tekrar apt-rdepends çağırmaktan çok daha hızlı olmasını beklerdim
muru

Yukarıdaki pythonkod, kodumdan (3 saat) 3600 kat daha hızlı (yani 3 saniye sürdü). Özyinelemeli sürümü test etmek için sabırsızlanıyoruz ...
agc

3

Aşağıdaki kabuk komut dosyası, yüklü tüm bağımlılıkların üst öğelerini arar.

function get_installed_packages() {
    apt list --installed | sed 's#/.*##'
}

function get_installed_packages_with_deps() {
    dpkg-query --show --showformat '${Package} ${Depends} \
        ${Pre-Depends}\n' $(get_installed_packages) | 
    sed 's/ ([^(]*)//g; s/:any\|,//g'
}

function get_package_relations() {
    awk '{print $1 " " $1; for(i = 2; i <= NF; i++) print $1 " " $i;}'
}

function add_marker() {
    echo "~ ~"
}

function resolve_parents() {
    tsort | sed -n '1,/~/ p' | head -n -1
}

(get_installed_packages_with_deps | get_package_relations; add_marker) | 
resolve_parents

Kullandığım tsortbu senaryodaki. Bağımlılık olmadan sonuna bir işaretleyici eklerken, işaretleyicinin sonucumda bağımlılık içermeyen son giriş olacağını da varsayıyorum. Böylece bağımlılıkları olmayan son paket ile bağımlılıkları olan ilk paket arasında ayrım yapabilirim.

Bu çözümle ilgili bir sorun fark ettim:
Bağımlılık grafiğinde döngüler var. Bu girişler tarafından yoksayılır tsort.


2

Elle yüklenen tüm paketleri 1. bağımlılık düzeyleri olmadan aşağıdaki gibi bulabilirsiniz:

apt-mark showmanual | sort > manually-installed.txt

apt show $(apt-mark showmanual) 2>/dev/null | 
grep -e ^Depends -e ^Pre-Depends > deps1.txt

cat deps1.txt | 
sed 's/^Depends: //; s/^Pre-Depends: //; 
     s/(.*)//g; s/:any//g' > deps2.txt

cat deps2.txt | tr -d ',|' | tr ' ' '\n' | grep -v ^$ |
sort -u > all-dep-packages.txt

grep -v -F -f all-dep-packages.txt manually-installed.txt

Aşağıdaki tek katmanlı sihri de kullanabilirsiniz:

apt-mark showmanual | sort | grep -v -F -f <(apt show $(apt-mark showmanual) 2> /dev/null | grep -e ^Depends -e ^Pre-Depends | sed 's/^Depends: //; s/^Pre-Depends: //; s/(.*)//g; s/:any//g' | tr -d ',|' | tr ' ' '\n' | grep -v ^$ | sort -u)

Çok daha hızlı. Bu, çoğunlukla OP kodunun bir üst kümesinin çıktısını verir , ancak dasherpaket gibi birkaçını da kaçırır . Benim sistemde OP kodu aracılığıyla taşınıyor sort -Vçıkışlar 475 hatları, MURU en kod çıkışları 914 , (dahil çizgiler dasher) ve bu cevabım kod çıkışları 995 satır.
agc

Evet, komut dosyam tam bağımlılık ağacını dikkate almıyor. Daha fazla hiyerarşi seviyesi için uyarlamayı deneyebilirsiniz.
sealor
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.