종속성없이 수동으로 설치된 최상위 패키지 목록


12

를 사용하여 수동으로 설치된 패키지를 표시하는 방법에는 여러 가지가 있습니다 apt.

apt-mark showmanual

그러나 때로는 그 결과가 너무 많습니다. 예를 들어 사용자가 수동으로 패키지를 설치 한 경우 foo:

apt-get install foo

...에 foo의존 하면 다음 barbaz같이 apt-mark showmanual출력됩니다.

bar
baz
foo

어떻게 우리는 최상위 레벨 수동으로 설치 패키지를 (나열 할 수 있습니다 즉, foo (의존성없이) 하지 baz않으며, bar)?


다음 코드는 작동하는 것으로 보이지만 GNU 가 수백 번 parallel호출 apt-rdepends하는 속도가 너무 느립니다 (4 코어 CPU로 3 시간).

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 시간짜리 코드의 슈퍼 세트를 출력하지만 initand과 같은 놀라움을 나타내지 않습니다 grep(적당한 데이터가 손상되었을 수 있습니까?), 너무 많은 라이브러리를 보여줍니다. OTOH, 내 3 시간 코드 는 위의 코드가 인쇄 하는 몇 가지 항목이 누락되었습니다python . 누락 된 항목이로 설치되지 않았을 수 있습니다 apt.
agc

@agc 아마도 재귀하지 않았기 때문일 것입니다. 주말 후에 재귀 적 옵션을 시도 할 것입니다. 심지어 재귀와 함께,하지만, 나는이 전화보다 빠른 방법으로 기대 반복적으로 APT-rdepends
muru

위의 python코드는 내 코드 (3 시간)보다 3600 배 빠릅니다 (즉, 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이 스크립트에서 사용 했습니다. 종속성없이 끝에 마커를 추가하면 마커가 결과에 종속성이없는 마지막 항목이 될 것이라고 가정합니다. 따라서 종속성이없는 마지막 패키지와 depenencies가있는 첫 번째 패키지를 구별 할 수 있습니다.

이 솔루션의 한 가지 문제점을 발견
했습니다. 종속성 그래프에주기가 있습니다. 해당 항목은로 무시됩니다 tsort.


2

다음과 같이 첫 번째 수준의 종속성없이 수동으로 설치된 모든 패키지를 찾을 수 있습니다.

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)

훨씬 더 빨리. 이것은 대부분 OP 코드의 상위 세트를 출력 하지만 dasher패키지 와 같은 몇 가지도 누락 됩니다. 내 시스템의 OP 코드를 통해 파이프 sort -V출력 475 선, muru의 코드 출력 (914 개) , (포함 라인 dasher),이 대답의 코드 출력 995 개 라인.
agc

예, 내 스크립트는 완전한 종속성 트리를 고려하지 않습니다. 더 많은 계층 레벨에 맞게 조정할 수 있습니다.
실러
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.