Liệt kê các gói được cài đặt thủ công mà không phụ thuộc vào chúng


11

Có nhiều cách để hiển thị các gói được cài đặt thủ công bằng cách sử dụng apt, chẳng hạn như:

apt-mark showmanual

Nhưng đôi khi đầu ra đó là quá nhiều. Ví dụ: nếu người dùng cài đặt gói thủ công foo:

apt-get install foo

... và foophụ thuộc vào barbazsau đó apt-mark showmanualsẽ xuất ra:

bar
baz
foo

Làm thế nào chúng ta chỉ có thể liệt kê các gói được cài đặt thủ công ( tức là foo ) mà không phụ thuộc vào chúng ( tức là không baz, cũng không bar)?


Đoạn mã sau có vẻ hoạt động, nhưng GNU parallel gọi apt-rdependsvài trăm lần thì quá chậm, (ba giờ với CPU 4 lõi):

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

Hừm. Các câu trả lời và mã OP đều rất khác nhau và trả về dữ liệu hơi khác nhau, rằng tôi đang hơi mờ về dữ liệu của phương thức nào là đúng nhất. Có lẽ cần có câu trả lời khảo sát, bắt đầu từ một hệ thống thử nghiệm tối thiểu và thêm một số chương trình một lúc để xem cách thức và thời điểm đầu ra thay đổi.
agc

Câu trả lời:


9

Điều này có thể được thực hiện bằng cách sử dụng API apt của Python. Các gói bạn nhìn thấy apt-mark showmanualchính xác là các gói trong apt.cache.Cache()đó is_installedlà đúng và is_auto_installedsai. Nhưng, dễ dàng hơn để xử lý các phụ thuộc:

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

Ngay cả điều này liệt kê một số gói mà tôi không mong đợi để xem ở đó ( init, grep?!).


Trên hệ thống của tôi, mã đó xuất ra một siêu mã của mã 3 giờ của tôi, nhưng không cho thấy bất ngờ nào giống như initgrep(có thể dữ liệu apt của bạn bị hỏng?), Nó cũng hiển thị quá nhiều thư viện. OTOH, mã 3 giờ của tôi bỏ lỡ một vài mục nên có, các mục mà pythonmã ở trên in. Có thể các mục còn thiếu chưa được cài đặt apt.
agc

@agc đó có lẽ là do tôi đã không tái diễn. Tôi sẽ thử một tùy chọn đệ quy sau cuối tuần. Tuy nhiên, ngay cả với đệ quy, tôi hy vọng điều này sẽ nhanh hơn nhiều so với việc gọi apt -rdepends liên tục
muru

pythonMã trên nhanh hơn 3600 lần (tức là mất 3 giây) so với mã của tôi (3 giờ). Mong được thử nghiệm phiên bản đệ quy ...
agc

3

Tập lệnh shell sau đây tìm kiếm cha mẹ của tất cả các phụ thuộc được cài đặt.

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

Tôi đã sử dụng tsorttrong kịch bản này. Tôi giả sử rằng khi thêm một điểm đánh dấu vào cuối mà không phụ thuộc thì điểm đánh dấu cũng sẽ là mục cuối cùng không có phụ thuộc trong kết quả của tôi. Vì vậy, tôi có thể phân biệt giữa gói cuối cùng mà không phụ thuộc và gói đầu tiên có phụ thuộc.

Tôi nhận thấy một vấn đề với giải pháp này:
Có các chu kỳ trong biểu đồ phụ thuộc. Những mục được bỏ qua bởi tsort.


2

Bạn có thể tìm thấy tất cả các gói được cài đặt thủ công mà không cần phụ thuộc cấp 1 như sau:

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

Bạn cũng có thể sử dụng phép thuật một lớp sau:

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)

Nhanh hơn nhiều. Điều này tạo ra phần lớn siêu mã OP, nhưng nó cũng bỏ lỡ một số, chẳng hạn như dashergói. Trên hệ thống của tôi, mã OP được dẫn qua sort -Vđầu ra 475 dòng, của muru cho ra 914 dòng, (bao gồm dasher) và mã của câu trả lời này tạo ra 995 dòng.
agc

Có, kịch bản của tôi không xem xét cây phụ thuộc hoàn toàn. Bạn có thể cố gắng điều chỉnh nó cho các cấp bậc cao hơn.
niêm phong
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.