ฉันต้องการรับรายการแพคเกจที่ติดตั้งด้วยตนเองโดยapt
หรือaptitude
และสามารถค้นหาว่ามีการfoobar
ติดตั้งแพคเกจด้วยตนเองหรือโดยอัตโนมัติ มีวิธีการทำอย่างประณีตจากบรรทัดคำสั่งหรือไม่
ฉันต้องการรับรายการแพคเกจที่ติดตั้งด้วยตนเองโดยapt
หรือaptitude
และสามารถค้นหาว่ามีการfoobar
ติดตั้งแพคเกจด้วยตนเองหรือโดยอัตโนมัติ มีวิธีการทำอย่างประณีตจากบรรทัดคำสั่งหรือไม่
คำตอบ:
คุณสามารถใช้หนึ่งในสอง liners อย่างใดอย่างหนึ่ง ทั้งคู่ให้ผลลัพธ์ที่เหมือนกันบนเครื่องของฉันและแม่นยำกว่าโซลูชันทั้งหมดที่เสนอจนถึงตอนนี้ (6 กรกฎาคม 2014) ในคำถามนี้
การใช้apt-mark
:
comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort -u)
การใช้aptitude
:
comm -23 <(aptitude search '~i !~M' -F '%p' | sed "s/ *$//" | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort -u)
แพคเกจน้อยมากยังคงตกอยู่ในรอยแตกแม้ว่าฉันจะสงสัยว่ามีการติดตั้งโดยผู้ใช้จริง ๆ ไม่ว่าหลังจากติดตั้งผ่านการตั้งค่าการแปลภาษาหรือเช่นผ่านตัวติดตั้ง Totem codec นอกจากนี้เวอร์ชันส่วนหัวของลินุกซ์ก็ดูเหมือนจะสะสมแม้ว่าฉันจะติดตั้ง metapackage ที่ไม่ใช่รุ่นเฉพาะเท่านั้น ตัวอย่าง:
libreoffice-help-en-gb
openoffice.org-hyphenation
gstreamer0.10-fluendo-mp3
linux-headers-3.13.0-29
มันทำงานอย่างไร:
sed
แถบเพิ่มเติมจะเหลือพื้นที่ว่างที่ท้ายบรรทัดความเป็นไปได้อื่น ๆ ก็ใช้งานไม่ได้เช่นกัน:
ubuntu-14.04-desktop-amd64.manifest
ไฟล์ ( ที่นี่สำหรับ Ubuntu 14.04) /var/log/installer/initial-status.gz
แทน แพคเกจเพิ่มเติมจะแสดงเป็นติดตั้งด้วยตนเองแม้ว่าจะไม่apt-mark showauto
ตัวอย่างเช่นไม่มีแพ็คเกจ xserver-xorg ในขณะที่ไฟล์อื่นทำ/var/log/installer/initial-status.gz
apt-mark
ฉันใช้โพสต์ StackExchange อื่น ๆ เป็นข้อมูลอ้างอิง แต่ก็ไม่มีวิธีใดทำงานได้ดีเหมือนโซลูชันข้างต้น:
ทั้งสองรายการมีแพ็คเกจมากกว่าโซลูชันด้านบน
แก้ไข: จะทำอย่างไรถ้าคุณอัพเกรดจากรุ่นก่อนหน้า:
หากคุณอัพเกรด Ubuntu จากรุ่นหนึ่งเป็นรุ่นถัดไปคุณอาจต้องปรับกระบวนการนี้ ในกรณีนั้นฉันจะตรวจสอบไฟล์รายการของรีลีสที่ใหม่กว่า (ดูด้านบน) นอกเหนือจากไฟล์ initial-status.gz จากรีลีสปัจจุบัน คุณสามารถทำได้โดยเพียงแค่เพิ่มการเปรียบเทียบอื่น การใช้ไฟล์ Manifest จะไม่ทำงานเนื่องจากไฟล์ Manifest ไม่ได้มีทุกอย่างที่ไฟล์ initial_status.gz ทำ (ฉันตรวจสอบแล้ว)
/var/log/installer/initial-status.gz
ขาดหายไป นอกจากนี้ฉันต้องการทราบว่านี้ขึ้นอยู่กับการทำเครื่องหมาย apts manual
หรือไม่?
showmanual
คำสั่ง (ด้านล่าง) และใช้comm
เพื่อเปรียบเทียบรายการทั้งสอง (เรียงลำดับ) showmanual
ผลให้ผม 1,840 เพิ่มเติมแพคเกจไม่ซ้ำกันจากapt-mark showmanual
ไม่ได้แสดงตามวิธีนี้ ไม่มีแพ็กเกจที่ไม่ซ้ำกันกับเอาต์พุตของcomm
คำสั่งนี้ ฉันคิดว่ามันน่าสนใจมากกว่าที่จะบันทึกว่าสำหรับพีซีของฉัน894แพ็คเกจมีการระบุไว้ในผลลัพธ์ทั้งสอง ไม่แน่ใจว่าทำไมมีความแตกต่างมากมาย แพคเกจบางรายการ (หลายรายการ) ดูเหมือนว่าจะออกวางจำหน่ายเฉพาะ คนอื่น ๆ เช่น xorg, ส่วนประกอบ GTK และlib*
สิ่งที่อาจมีการปรับปรุง อย่างไรก็ตามคำตอบนี้เป็นการเริ่มต้นที่ดีมาก
apt-mark showmanual
ฉันเพียงแค่เมื่อเทียบกับการแก้ปัญหาของคุณ มันน่าสนใจที่เห็นความแตกต่างมากมาย รายการของคุณมี 238 แพ็คเกจในขณะที่ showmanual ส่งคืนแพ็คเกจ 1717 รายการ ในแพคเกจที่ติดตั้ง 2179 มีเพียง 223 ในทั้งสองรายการ 15 เฉพาะในของคุณ (ตัวอย่าง: nodejs, lightdm) และ 223 อยู่ใน showmanual เท่านั้น (ตัวอย่าง: xserver-xorg, ubuntu-desktop) รู้สึกว่ารายการของคุณมีประโยชน์มากกว่า แต่ไม่ทราบว่าความแตกต่างเหล่านี้มาจากไหนมันไม่ใช่เรื่องง่ายที่จะตัดสินใจ ... (แต่ฉันค่อนข้างแน่ใจว่าฉันติดตั้ง nginx และ lightdm ด้วยตนเอง ... ) [ขอโทษทีฉันจะเขียน เหมือนกัน;)]
ในเวอร์ชันที่ใหม่กว่าของแพ็คเกจ apt ยังมีคำสั่ง apt-mark
apt-mark showmanual
linux-image-3.11.0-*-generic
ว่าเป็นคู่มือ ฯลฯ
linux-image-3.13.0-24-generic
เป็นคู่มือ แต่ปัจจุบันlinux-image-3.13.0-27-generic
เป็นไปโดยอัตโนมัติ ดูเหมือนว่าการอัพเกรดของแพคเกจการอ้างอิง (ในกรณีนี้linux-image-generic
ซึ่งเปลี่ยนการอ้างอิง) เครื่องหมายคู่มือจะถูกตั้งค่าโดยอัตโนมัติ
apt-get autoremove
หากไม่มีแพคเกจทำเครื่องหมายเป็นคู่มือระบบทั้งหมดจะถูกลบออกด้วย นี่ไม่ใช่สิ่งที่คุณต้องการอย่างแน่นอน
สำหรับ Ubuntu 16.04 /var/log/apt/history.log
ตรวจสอบไฟล์บันทึก
ตัวอย่างเช่น:
zgrep 'Commandline: apt' /var/log/apt/history.log /var/log/apt/history.log.*.gz
มันไม่สมบูรณ์แบบ แต่มันก็ค่อนข้างดีที่ทำให้ชัดเจนว่าสิ่งที่ฉันติดตั้งด้วยมือ วาง-B 1
บน grep เพื่อดูว่าเมื่อมันถูกติดตั้ง
ตัวอย่างผลลัพธ์
Commandline: apt install postgresql-9.5-plv8
Commandline: aptdaemon role='role-install-file' sender=':1.85'
Commandline: apt install task
Commandline: apt autoremove
Commandline: apt install atom
Commandline: apt upgrade
Commandline: apt-get install asciinema
Commandline: apt install iperf3
Commandline: apt upgrade
Commandline: apt-get install chromium-browser
Commandline: apt install joe cpanminus build-essential postgresql libdbd-pg-perl libcrypt-openssl-bignum-perl libcrypt-openssl-rsa-perl libio-socket-ssl-perl libnet-ssleay-perl libssl-dev
Commandline: aptdaemon role='role-commit-packages' sender=':1.2314'
Commandline: apt install git
Commandline: apt install sqlite
Commandline: apt install whois
Commandline: apt install libdbd-pg-perl
Commandline: apt install perl-doc
Commandline: apt upgrade
ไม่แน่ใจว่าจะหยิบขึ้นมาaptitude
หรือไม่ ดูเหมือนจะไม่ได้รับการติดตั้งจากแอพ Desktop Software ของ Ubuntu
apt-mark showauto | grep -iE '^foobar$'
จะส่งออก "foobar" ถ้าแพ็คเกจถูกติดตั้งโดยอัตโนมัติไม่มีอะไรเป็นอย่างอื่น
aptitude search '!~M ~i'
จะแสดงรายการแพคเกจที่ไม่ได้ติดตั้งโดยอัตโนมัติ มันเป็นความถนัดที่น่าเสียดายที่ไม่ได้เป็นส่วนหนึ่งของการติดตั้งเริ่มต้นบน Ubuntu Desktop ตั้งแต่ 10.10
aptitude search
แสดงให้เห็นถึงแพ็คเกจทั้งหมดไม่ใช่แค่ชุดที่ติดตั้งด้วยตนเอง (ฉันคิดว่านั่นเป็นสิ่งที่ OP ต้องการ)
aptitude search '!~M ~i'
และมีรายชื่อแพ็คเกจ 1043 รายการ ไม่มีวิธีที่ฉันติดตั้งแพ็คเกจจำนวนมากด้วยตนเอง
สคริปต์ต่อไปนี้จะพิมพ์แพ็คเกจทั้งหมดที่ไม่ได้ตั้งค่าเป็นการติดตั้งอัตโนมัติและด้วยเหตุนี้จึงถูกติดตั้งด้วยตนเอง:
#!/usr/bin/python
try:
import apt_pkg
except ImportError:
print "Error importing apt_pkg, is python-apt installed?"
sys.exit(1)
apt_pkg.init()
STATE_FILE = apt_pkg.config.find_dir("Dir::State") + "extended_states"
auto = set()
tagfile = apt_pkg.TagFile(open(STATE_FILE))
while tagfile.step():
pkgname = tagfile.section.get("Package")
autoInst = tagfile.section.get("Auto-Installed")
if not int(autoInst):
auto.add(pkgname)
print "\n".join(sorted(auto))
มันขึ้นอยู่กับวิธีการที่ apt-mark พิมพ์แพ็คเกจที่ติดตั้งโดยอัตโนมัติ
sys.exit(1)
โดยไม่มีimport sys
อาจส่งผลให้เกิดข้อผิดพลาดในงูหลามรุ่นใหม่กว่า อย่างใดอย่างหนึ่งหรือการใช้งานimport sys
exit(1)
ในการรับรายการแพคเกจทั้งหมด (ไม่ได้ติดตั้งติดตั้งโดยผู้ใช้หรือติดตั้งโดยค่าเริ่มต้นใน PPAs ทั้งหมด) apt
ใช้วิธีการต่อไปนี้:
apt list [option]
ตัวเลือกที่เป็นไปได้มีประโยชน์สำหรับสิ่งนี้คือ:
--installed
เพื่อแสดงเฉพาะแพ็คเกจที่ติดตั้งบนระบบ (จากทั้งหมด 50,000+ รายการ)
--manual-installed
เพื่อแสดงรายการแพ็กเกจที่ติดตั้งอย่างชัดเจนโดยคำสั่งโดยตรงหรือเป็นการอ้างอิง
หรือคุณสามารถทำได้:
apt list --manual-installed | grep -F \[installed\]
เพื่อรับรายการแพ็กเกจที่เป็นผลมาจากคำสั่งของผู้ใช้และการอ้างอิงของพวกเขาเท่านั้นและเพื่อรับข้อมูลเพิ่มเติมเกี่ยวกับพวกเขาเช่นเวอร์ชันและสถาปัตยกรรมที่รองรับ (x86, x86_64, amd64, all, etc. )
ในฐานะที่เป็นคนหลายคนแสดงความคิดเห็น apt-mark showmanual ดูเหมือนว่าจะเป็นรถบั๊กกี้เล็กน้อย (และฉันรายงานว่าเป็นข้อผิดพลาด 727799 ) เมื่อฉันใช้มันจริง ๆ แล้วรายงานสิ่งต่าง ๆ มากมายที่ไม่ได้เข้าสู่ระบบ / var / lib / apt / extended_states (ที่นี้ควรจะเก็บไว้) และ apt-get ไม่ได้บันทึกสิ่งที่ติดตั้งใน / var / lib / apt / extended_states (เพียงใน / var / lib / dpkg / สถานะ) สคริปต์ python โดย txwikinger ด้านบนดึงมาจาก / var / lib / apt / extended_states โดยตรง แต่ถ้าคุณใช้วันนี้ไวยากรณ์อาจไม่ทำงาน (ของฉันเพิ่งเริ่มสร้างข้อผิดพลาดกับ Kubuntu 13.10) ไวยากรณ์ที่อัปเดตคือ:
#!/usr/bin/python
import sys
try:
import apt_pkg
except ImportError:
print "Error importing apt_pkg, is python-apt installed?"
sys.exit(1)
apt_pkg.init()
STATE_FILE = apt_pkg.config.find_dir("Dir::State") + "extended_states"
auto = set()
tagfile = apt_pkg.TagFile(open(STATE_FILE))
while tagfile.step():
pkgname = tagfile.section.get("Package")
autoInst = tagfile.section.get("Auto-Installed")
if not int(autoInst):
auto.add(pkgname)
print "\n".join(sorted(auto))
สำหรับฉันนี่เป็นรายการสั้น ๆ 5 รายการซึ่งดูเหมือนจะไม่ถูกต้องเช่นกัน
sys.exit(1)
โดยไม่มีimport sys
อาจส่งผลให้เกิดข้อผิดพลาดในงูหลามรุ่นใหม่กว่า อย่างใดอย่างหนึ่งหรือการใช้งานimport sys
exit(1)
ฉันต้องการให้โซลูชัน GUI
เปิด Synaptic Package Manager
ไปที่ Status
คลิก Installed (manual)
มันจะให้รายการแพคเกจที่ติดตั้งด้วยตนเองโดย apt หรือ aptitude
น่าเสียดายที่ฉันไม่พบตัวเลือกใด ๆ ในCustom Filters
การตรวจสอบว่ามีการfoobar
ติดตั้งแพคเกจด้วยตนเองหรือโดยอัตโนมัติ
หากแพ็กเกจอยู่ภายใต้Installed
แต่ไม่อยู่ภายใต้แสดงInstalled (manual)
ว่ามีการติดตั้งโดยอัตโนมัติ หากแพ็คเกจอยู่ภายใต้แสดงInstalled (manual)
ว่ามีการติดตั้งด้วยตนเอง
ถ้าไม่มีใครให้คำตอบที่ดีโดยใช้คำสั่ง เม.ย. สิ่งที่คุณสามารถทำมันวิธีที่ยาก Apt-get เก็บข้อมูลไว้ใน / var / lib / apt / extended_states ไฟล์ใด ๆ ที่ติดตั้งโดยอัตโนมัติจะถูกเพิ่มลงในไฟล์นี้ หากคุณติดตั้งแพคเกจแล้วในไฟล์นี้ด้วยตนเองแพ็คเกจจะยังคงอยู่ในไฟล์นี้ แต่ติดตั้งอัตโนมัติ: 0 ในบรรทัดที่สอง มันไม่ถูกลบ
หมายเหตุ: ตามที่คาดไว้คำตอบที่ดีกว่าซึ่งน่าจะใช้ได้ถ้าการเปลี่ยนแปลงตำแหน่งไฟล์ปรากฏขึ้น ฉันเก็บไว้ในกรณีที่ข้อมูลเกี่ยวกับตำแหน่งไฟล์นั้นมีประโยชน์
apt-get install liferea
และมันไม่ได้ติดตั้ง แต่ฉันได้รับผลลัพธ์ที่เป็นสิ่งที่มีผลต่อการ "ทำเครื่องหมายว่าติดตั้งด้วยตนเอง" ตอนนี้ Liferea ยังคงอยู่ในไฟล์ยกเว้นบรรทัดถัดไปมีแทน0
1
นอกจากนี้คุณควรเปลี่ยนรูปแบบ regex ของคุณเพื่อแทนเพียง" foobar$"
foobar
หลังจาก googling ไปมากฉันก็สามารถรวบรวมสคริปต์นี้ได้ มันใช้งานได้ดีสำหรับฉัน:
# List of all packages currently installed
current=$(dpkg -l | awk '{print $2}' | sort | uniq)
# List of all packages that were installed with the system
pre=$(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort | uniq)
# List of packages that don't depend on any other package
manual=$(apt-mark showmanual | sort | uniq)
# (Current - Pre) ∩ (Manual)
packages=$(comm -12 <(comm -23 <(echo "$current") <(echo "$pre")) <(echo "$manual") )
for pack in $packages; do
packname=$(echo $pack | cut -f 1 -d ":")
desc=$(apt-cache search "^$packname$" | sed -E 's/.* - (.*)/\1/')
date=$(date -r /var/lib/dpkg/info/$pack.list)
echo "# $desc"
echo "# $date"
echo "sudo apt-get install $pack"
echo -e ""
done
sort -u
sort | unique
ในฐานะที่apt-mark
ไม่แสดงสถาปัตยกรรมที่คุณควรจะดึงมันออกมาจาก dpkg เอาท์พุทก่อนที่จะดำเนินงานที่ตั้งไว้ (หรือใช้dpkg-query -W -f='${Package}\n'
) นอกจากนี้ dpkg อาจแสดงรายการแพ็คเกจที่ไม่ได้ติดตั้งในปัจจุบัน สำหรับ "desc" คุณสามารถใช้ `dpkg-query -W -f = '# $ {binary: Summary} \ n' $ pack ซึ่งเร็วกว่า
apt-mark
อาจแสดงสถาปัตยกรรมสำหรับแพคเกจบางอย่าง dpkg -l
แต่ไม่ได้สำหรับจำนวนมากดังนั้นตาม
apt-cache search
ช้า การรับรายการวันที่ติดตั้งล่วงหน้าโดยใช้บางอย่างเช่นhelp.ubuntu.com/community/ListInstalledPackagesByDateอาจมีประสิทธิภาพมากขึ้น
ในฐานะที่เป็น Li Lo กล่าวว่าคุณapt-mark showauto
ควรได้รับรายชื่อของสิ่งที่ติดตั้งโดยอัตโนมัติ
ตอนนี้เพื่อแสดงสิ่งที่ติดตั้งด้วยตนเองมันกลับกลายเป็นว่ามีตัวแก้ไขการค้นหาที่เรียบง่ายน่ารักสำหรับความถนัด แต่คุณไม่ต้องการทำเช่นนั้น คุณต้องการเขียนคำสั่ง bash ขนาดใหญ่ที่ทำวิทยาศาสตร์จรวด
หมายเหตุ:นี่เป็นภาพประกอบที่แสดงให้เห็นว่าคุณเจ๋งมากแค่ไหนที่ดูคำสั่งทุบตีขนาดใหญ่กับเพื่อนของคุณ
comm -3 <(dpkg-query --show -f '${Package} ${Status}\n' | \n
grep "install ok installed" | cut --delimiter=' ' -f 1) <(apt-mark showauto)
ฉันทำลายมันลงบนสองบรรทัดเพื่อให้สามารถอ่านได้ สิ่งนี้ทำอะไร
apt-mark
comm -3 <(dpkg -l | grep '^ii' | cut -d \ -f 3|sort) <(apt-mark showauto|sort)
ดีกว่า;)
นี่จะแสดงรายการแพ็กเกจที่ติดตั้งด้วยตนเองทั้งหมดโดยไม่ต้อง: การพึ่งพา, แพ็กเกจที่ถอนการติดตั้ง, แพ็คเกจที่ติดตั้งระหว่างการติดตั้งระบบ
unopts() {
in=`cat`
echo "$in" | sed -r 's/ --[^ ]+//g;s/ -[^ ]+//g'
}
list() {
cat '/var/log/apt/history.log' |
grep --color=never -v '\-o APT::Status-Fd=4 \-o APT::Keep-Fds::=5 \-o APT::Keep-Fds::=6' |
egrep --color=never "Commandline: apt-get.* $1" |
sed -r "s/Commandline: apt-get//;s/ $1//" |
unopts |
tr ' ' '\n' |
sed '/^$/d'
}
hapt() {
tmp=`mktemp -d`
installed=$tmp/installed
deleted=$tmp/deleted
dpkg=$tmp/dpkg
list 'install' > $installed
list '(remove|purge|autoremove)' > $deleted
dpkg --get-selections |
grep -v 'deinstall' |
cut -f 1 > $dpkg
while read package
do
sed -i "0,/$package/{//d;}" $installed
done < $deleted
while read package
do
if [ -z "`grep --color=never "^$package$" $dpkg`" ]
then
sed -i "0,/$package/{//d;}" $installed
fi
done < $installed
cat $installed
rm -r $tmp
}