를 사용하여 수동으로 설치된 패키지를 표시하는 방법에는 여러 가지가 있습니다 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
하는 속도가 너무 느립니다 (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
답변
이것은 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
?!) 가 나열되어 있습니다 .
답변
다음 쉘 스크립트는 설치된 모든 종속성의 부모를 검색합니다.
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
.
답변
다음과 같이 첫 번째 수준의 종속성없이 수동으로 설치된 모든 패키지를 찾을 수 있습니다.
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)