แสดงรายการแพ็คเกจที่ติดตั้งด้วยตนเองระดับสูงสุดโดยไม่มีการอ้างอิง


12

มีหลายวิธีในการแสดงแพ็คเกจที่ติดตั้งด้วยตนเองโดยใช้aptเช่น:

apt-mark showmanual

แต่บางครั้งผลลัพธ์นั้นมากเกินไป ตัวอย่างเช่นถ้าผู้ใช้ติดตั้งแพ็กเกจด้วยตนเองfoo:

apt-get install foo

... และfooขึ้นอยู่กับbarและbazจากนั้นapt-mark showmanualจะส่งออก:

bar
baz
foo

เราจะแสดงรายการเฉพาะแพ็คเกจระดับบนสุดที่ติดตั้งด้วยตนเองได้ ( เช่น foo ) โดยไม่มีการขึ้นต่อกัน ( เช่นไม่ใช่bazหรือbar)


ดูเหมือนว่ารหัสต่อไปนี้จะทำงานได้ แต่GNU ที่ parallelเรียกapt-rdependsสองสามร้อยครั้งช้าเกินไป (สามชั่วโมงด้วย CPU 4 คอร์):

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

อืมมม คำตอบและรหัส OP นั้นแตกต่างกันมากและส่งคืนข้อมูลที่แตกต่างกันเล็กน้อยซึ่งฉันได้รับค่อนข้างคลุมเครือซึ่งข้อมูลของวิธีการนั้นถูกต้องที่สุด บางทีอาจต้องการคำตอบแบบสำรวจโดยเริ่มจากระบบทดสอบขั้นต่ำและเพิ่มโปรแกรมในแต่ละครั้งเพื่อดูว่าเวลาและเวลาต่างกันอย่างไร
agc

คำตอบ:


9

สิ่งนี้สามารถทำได้โดยใช้ Python apt API แพ็คเกจที่คุณเห็นapt-mark showmanualนั้นเป็นแพคเกจapt.cache.Cache()ที่is_installedเป็นจริงและis_auto_installedเป็นเท็จ แต่มันง่ายกว่าในการประมวลผลการพึ่งพา:

#! /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))

แม้นี้จะแสดงรายการแพคเกจบางอย่างที่ฉันไม่คาดหวังที่จะเห็นมี ( init, grep?!)


ในระบบของฉันที่รหัสแสดงผลเป็นชุดของรหัส 3 ชั่วโมงของฉัน แต่ไม่แสดงความประหลาดใจเช่นinitและgrep(บางทีข้อมูล apt ของคุณเสียหาย?) นอกจากนี้ยังแสดงห้องสมุดมากเกินไป OTOH รหัส 3 ชั่วโมงของฉันพลาดรายการบางอย่างที่ควรมีรายการที่pythonโค้ดด้านบนพิมพ์ออกมา aptอาจจะเป็นรายการที่หายไปไม่ได้ถูกติดตั้งกับ
agc

@agc นั่นอาจเป็นเพราะฉันไม่ได้เรียกคืน ฉันจะลองใช้ตัวเลือกซ้ำหลังจากสุดสัปดาห์ แม้ว่าจะมีการเรียกซ้ำแม้ว่าฉันจะคาดหวังว่าวิธีนี้จะเร็วกว่าการเรียก apt-rdepends ซ้ำ ๆ
muru

pythonรหัสข้างต้นคือ 3600 ครั้งเร็วขึ้น (เช่นใช้เวลา 3 วินาที) กว่ารหัสของฉัน (3 ชั่วโมง) รอคอยที่จะทดสอบเวอร์ชันซ้ำ ...
agc

3

เชลล์สคริปต์ต่อไปนี้ค้นหาพาเรนต์ของการขึ้นต่อกันที่ติดตั้งทั้งหมด

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

ฉันใช้tsortในสคริปต์นี้ ฉันคิดว่าเมื่อเพิ่มเครื่องหมายที่สิ้นสุดโดยไม่มีการอ้างอิงเครื่องหมายจะเป็นรายการสุดท้ายโดยไม่มีการอ้างอิงในผลลัพธ์ของฉัน ดังนั้นฉันสามารถแยกความแตกต่างระหว่างแพคเกจล่าสุดโดยไม่ต้องพึ่งพาและแพคเกจแรกที่มีการพึ่งพา

ฉันสังเกตเห็นปัญหาหนึ่งกับวิธีแก้ปัญหานี้:
มีรอบในกราฟพึ่งพา tsortรายการเหล่านั้นจะถูกละเลยโดย


2

คุณสามารถค้นหาแพ็คเกจที่ติดตั้งด้วยตนเองทั้งหมดโดยไม่ต้องพึ่งพาระดับที่ 1 ดังต่อไปนี้:

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

คุณยังสามารถใช้เวทมนต์หนึ่งซับต่อไปนี้:

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)

เร็วขึ้นมาก ผลลัพธ์นี้เป็นสิ่งที่ส่วนใหญ่เป็น superset ของรหัส OP แต่ก็ยังขาดบางอย่างเช่นdasherแพคเกจ ในระบบของฉันรหัส OP ประปาผ่านsort -Vเอาท์พุท475เส้นMuru ของรหัสเอาท์พุท914เส้น (รวมdasher) และของคำตอบนี้เอาท์พุทรหัส995เส้น
agc

ใช่สคริปต์ของฉันไม่ได้พิจารณาโครงสร้างการพึ่งพาที่สมบูรณ์ คุณสามารถลองปรับระดับเพิ่มเติมได้
ปิดผนึก
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.