Daftar paket pada sistem berbasis apt dengan tanggal instalasi

104

Bagaimana saya bisa mendaftar paket yang diinstal berdasarkan tanggal instalasi?

Saya perlu melakukan ini di debian / ubuntu. Jawaban untuk distribusi lain juga bagus.

Saya menginstal banyak hal untuk mengkompilasi sepotong kode tertentu, dan saya ingin mendapatkan daftar paket yang harus saya instal.

Elazar Leibovich
sumber
1
Saya mencari di Google untuk "tanggal rilis yang tepat" tanpa hasil, mungkin komentar ini akan membantu para googler di masa depan.
ThorSummoner
Pertanyaan serupa di askubuntu.com "Cara mendaftar semua paket yang diinstal" .
JamesThomasMoon1979

Jawaban:

67

Distribusi berbasis RPM seperti Red Hat mudah:

rpm -qa --last

Pada Debian dan distribusi berbasis dpkg lainnya, masalah khusus Anda juga mudah:

grep install /var/log/dpkg.log

Kecuali jika file log telah diputar, dalam hal ini Anda harus mencoba:

grep install /var/log/dpkg.log /var/log/dpkg.log.1

Secara umum, dpkgdan aptsepertinya tidak melacak tanggal pemasangan, terjadi karena tidak adanya bidang seperti itu di dpkg-queryhalaman manual.

Dan akhirnya /var/log/dpkg.log.*file lama akan dihapus oleh rotasi log, sehingga cara itu tidak dijamin memberi Anda seluruh sejarah sistem Anda.

Salah satu saran yang muncul beberapa kali (misalnya utas ini ) adalah untuk melihat /var/lib/dpkg/infodirektori. File-file di sana menyarankan Anda untuk mencoba sesuatu seperti:

ls -t /var/lib/dpkg/info/*.list | sed -e 's/\.list$//' | head -n 50

Untuk menjawab pertanyaan Anda tentang pilihan, berikut ini pass pertama.

buat daftar paket berdasarkan tanggal

$ find /var/lib/dpkg/info -name "*.list" -exec stat -c $'%n\t%y' {} \; | \
    sed -e 's,/var/lib/dpkg/info/,,' -e 's,\.list\t,\t,' | \
    sort > ~/dpkglist.dates

membangun daftar paket yang diinstal

$ dpkg --get-selections | sed -ne '/\tinstall$/{s/[[:space:]].*//;p}' | \
    sort > ~/dpkglist.selections

bergabunglah dengan 2 daftar

$ join -1 1 -2 1 -t $'\t' ~/dpkglist.selections ~/dpkglist.dates \
    > ~/dpkglist.selectiondates

Untuk beberapa alasan itu tidak mencetak banyak perbedaan bagi saya, jadi mungkin ada bug atau asumsi yang tidak valid tentang apa --get-selectionsartinya.

Anda jelas dapat membatasi paket baik dengan menggunakan find . -mtime -<days>atau head -n <lines>, dan mengubah format output yang Anda inginkan, misalnya

$ find /var/lib/dpkg/info -name "*.list" -mtime -4 | \
    sed -e 's,/var/lib/dpkg/info/,,' -e 's,\.list$,,' | \
    sort > ~/dpkglist.recent

$ join -1 1 -2 1 -t $'\t' ~/dpkglist.selections ~/dpkglist.recent \
    > ~/dpkglist.recentselections

untuk hanya daftar pilihan yang diinstal (diubah?) dalam 4 hari terakhir.

Anda mungkin bisa juga menghapus sortperintah setelah memverifikasi urutan yang digunakan oleh dpkg --get-selectionsdan membuat findperintah lebih efisien.

Mikel
sumber
8
Saya biasanya suka apt-getlebih dari itu rpm, tetapi sekarang debian mendapatkan -1 karena tidak menyimpan tanggal instalasi dalam database. Trik debian mencakup semua paket yang diinstal, bukan hanya paket yang dipilih , tetapi juga merupakan awal yang baik.
Elazar Leibovich
Untuk Debian Anda mendapatkan lebih sedikit cruft (menghapus half-installedentri) jika Anda melakukannya:grep install\ /var/log/dpkg.log
Pierz
@Mikel - Jawaban yang bagus. Saya memperluas info file 'kumpulkan /var/lib/dpkg/info/*.list' dan menambahkan kode untuk menyaring semua kecuali "paket tingkat atas" (paket atp yang tidak bergantung pada paket atp lain). < Askubuntu.com/a/948532/723997 > tiang menjawab pertanyaan "Bagaimana saya bisa melihat riwayat perintah instalasi apt-get yang saya jalankan secara manual? ".
Craig Hicks
1
Debian / Ubuntu: grep " install " /var/log/dpkg.loghanya mencantumkan baris "instal" daripada menunjukkan yang "status" juga.
hidangan penutup
Jika tidak apt atau dpkg toko menginstal / memodifikasi datetime, yang tampaknya cukup tidak dapat diterima bagi saya pada tahun 2019. Kami mengandalkan grepping file log yang mungkin atau tidak masih pada mesin? Bagaimana ini masalahnya?
theferrit32
20

Mikel telah menunjukkan bagaimana melakukan ini di level dpkg . Khususnya, /var/lib/dpkg/info/$packagename.listdibuat ketika paket diinstal (dan tidak dimodifikasi setelahnya).

Jika Anda menggunakan alat APT (yang mungkin Anda lakukan karena Anda khawatir tentang paket yang secara otomatis vs yang diinstal secara manual), ada riwayat di /var/log/apt/history.log. Selama belum diputar, ia tetap melacak semua instalasi, peningkatan, dan penghapusan APT, dengan anotasi untuk paket yang ditandai sebagai diinstal secara otomatis. Ini adalah fitur yang cukup baru, diperkenalkan di APT 0.7.26, sehingga di Debian muncul dalam keadaan terjepit. Di Ubuntu, 10,04 memiliki history.logtetapi anotasi yang diinstal secara otomatis tidak ada sampai 10,10.

Gilles
sumber
1
Seperti yang ditunjukkan Mikel: "Dan akhirnya file /var/log/dpkg.log.* lama akan dihapus oleh rotasi log, jadi cara itu tidak dijamin memberi Anda seluruh sejarah sistem Anda.". Lihat ini < askubuntu.com/a/948532/723997 > jawaban untuk cara mendeteksi paket tingkat atas saat ini (artinya yang di mana tidak ada paket lain bergantung)
Craig Hicks
5

Kasar, tetapi bekerja:

for fillo in `ls -tr /var/lib/dpkg/info/*.list` ; 
    do basename ${fillo} | sed 's/.list$//g' ; 
done > forens.txt

ls -ltr /var/lib/dpkg/info/*.list > forentime.txt

for lint in `cat forens.txt` ; do 
    echo -n "[ ${lint} Installed ] : " ; 
    echo -n "`grep /${lint}.list forentime.txt | awk '{ print $6, $7, $8 }'` : " ; 
    ( ( grep -A3 " ${lint}$" /var/lib/apt/extended_states | \
        grep '^Auto' > /dev/null ) && echo "Auto" ) || echo "Manual" ; 
done > pkgdatetime.txt
Dulantha
sumber
2
Boo, desis untuk parsing output dari ls. Lihat mywiki.wooledge.org/ParsingLs untuk catatan tentang mengapa ini berbahaya / secara inheren bermasalah - opsi yang lebih aman adalah dengan menggunakan salah satu find -printfatau stat --formatuntuk menghasilkan aliran yang dapat diuraikan secara jelas.
Charles Duffy
@CharlesDuffy Tautan yang bagus, tetapi untuk tujuan kesederhanaan, menggunakan ls -al --time-style=long-isoharus membantu. Selain itu, mungkin belum pernah ada orang yang menamai paket APT dengan \n\t\r\vnamanya.
not2qubit
4

The /var/log/apt/history.logberkas memiliki format IMHO canggung.

Tanggal Mulai: {tanggal} {waktu} Baris Perintah: {perintah} {opsi ...} Pasang: {paket (versi)}, ..., {paket (versi)}, ... Tanggal Akhir: {tanggal } {waktu}

Saya lebih suka catatan format file log lebih

{tanggal} {waktu} {tab} {paket} {tab} {versi} {tab} {perintah} {opsi} \ n

atau XML yang menunjukkan tidak hanya {paket} tetapi {dependensi} apa pun.

Seperti yang saat ini diterapkan, Anda dapat menemukan informasi yang Anda cari tetapi memerlukan beberapa proses forensik untuk mengekstrak detailnya.

Saint DanBert
sumber
3

Ini berfungsi bagi saya pada sistem Debian, saya menduga format file telah berubah sejak 2011. Sistem ini cukup segar sehingga saya tidak berharap ini bekerja pada sistem yang lebih lama, meskipun itu mungkin hanya memerlukan unzip log dan menggunakan gumpalan untuk merujuk mereka semua.

grep 'install ' /var/log/dpkg.log.1 | sort | cut -f1,2,4 -d' '

Dua bidang pertama di setiap baris file /var/log/dpkg.logadalah tanggal dan waktu. Perhatikan ruang trailing dengan instal di bagian grep, ini karena pemutakhiran dapat memicu pemasangan tetapi jika saya mengerti dengan benar Anda ingin tahu apa yang diinstal oleh pengguna.

Amias
sumber
1
Persis apa yang saya lakukan. Mudah. Tetapi Anda dapat menggunakan zgrep dan semua log .gz Anda akan dicari seperti zgrep 'install' /var/log/dpkg.log*. Tempatkan spasi sebelum kata "instal" untuk mencegah "setengah instal" sial itu. Saya harus menggunakan cut -f1,5 untuk mendapatkan bidang nama paket. Tentu saja akhirnya log lama diputar.
geoO
2

Ini adalah satu-baris yang diinginkan dan dibutuhkan setiap orang:

for x in $(ls -1t /var/log/dpkg.log*); do zcat -f $x |tac |grep -e " install " -e " upgrade "; done |awk -F ":a" '{print $1 " :a" $2}' |column -t

Hasilnya akan menampilkan semua paket (baru) yang diinstal dan ditingkatkan dalam urutan kronologis.

Penjelasan garis:

  • ls -1t- dapatkan semua dpkg.log*nama file dalam urutan kronologis
  • zcat -f- JIKA file berjenis gzip lalu dekompres, ELSE hanya meneruskan konten.
  • tac- Membalikkan output kucing , baris demi baris untuk memastikan kami mendapatkan urutan kronologis yang benar.
  • grep- Hanya memeriksa paket yang diinstal atau ditingkatkan .
  • awk -F ':a'- Pisahkan bidang arsitektur dari nama paket
  • column -t - Cukup cetak kolom yang dipisahkan oleh ruang

Orang tentu saja ingin membuat alias untuk ini, tetapi sayangnya tidak mungkin karena awk tergantung pada tanda kutip tunggal dan ganda. Dalam hal ini sebaiknya dimasukkan ke dalam skrip bash dan di mana :pemisah ditangani lebih baik untuk arsitektur lain di kolom bidang.

Outputnya adalah:

2018-03-06  18:09:47  upgrade  libgomp1                     :armhf  6.3.0-18+rpi1                 6.3.0-18+rpi1+deb9u1
2018-03-05  15:56:23  install  mpg123                       :armhf  <none>                        1.23.8-1
2018-03-05  15:56:23  install  libout123-0                  :armhf  <none>                        1.23.8-1
2018-01-22  17:09:45  install  libmailtools-perl            :all    <none>                        2.18-1
2018-01-22  17:09:44  install  libnet-smtp-ssl-perl         :all    <none>                        1.04-1

Kekurangan:

  • Seperti yang ditunjukkan di atas, ini hanya bekerja pada arsitektur ARM dan perlu sedikit modifikasi untuk pemisah bidang arsitektur
  • Perlu dimasukkan ke dalam skrip untuk alias mudah
  • Belum diuji di sistem * nix lainnya
not2qubit
sumber
1

Memperhatikan hal ini karena Anda menyebutkan bahwa jawaban distribusi lain diperbolehkan. rpm memiliki seperangkat tag format output yang besar, salah satunya adalah INSTALLTIME. (Menggunakan wgetsebagai contoh)

rpm -qi wget --qf "%{NAME},%{INSTALLTIME}\n" | tail -n 1
wget,1454014156

Ini dapat diformat dalam beberapa cara. Saya menggunakannya dengan cara ini:

rpm -qi wget --qf "%{NAME},%{INSTALLTIME:date}\n" | tail -n 1
wget,Thu 28 Jan 2016 03:49:16 PM EST

Dua halaman ini memiliki banyak info hebat untuk memecahkan masalah metadata RPM:

http://www.rpm.org/max-rpm/s1-rpm-query-parts.html

http://www.rpm.org/max-rpm/s1-rpm-query-handy-queries.html

Menyortir informasi ini akan memberi Anda solusi yang berfungsi untuk masalah Anda.

Jonathan Swift
sumber
1

GNU / Linux Debian tidak memiliki alat bawaan untuk masalah ini, tetapi semua informasi tentang program yang diinstal dengan cara standar disimpan dalam file dengan nama -program.daftar di lokasi / var / lib / dpkg / info / . Tetapi tidak ada informasi tentang program yang diinstal secara manual di sana.


Solusi garis panjang yang panjang :

for file_list in `ls -rt /var/lib/dpkg/info/*.list`; do \
    stat_result=$(stat --format=%y "$file_list"); \
    printf "%-50s %s\n" $(basename $file_list .list) "$stat_result"; \
done

Penjelasan :

  1. ls -rtoutput file diurutkan berdasarkan modifikasi tanggal dalam urutan terbalik, yaitu dengan file terbaru di akhir daftar.
  2. stat mencetak tanggal file dalam bentuk yang dapat dibaca manusia.
  3. printf menampilkan nama paket dan tanggal modifikasi terakhirnya.
  4. The forLoop secara keseluruhan nama cetak paket dan tanggal dari yang terlama ke terbaru.

Contoh keluaran (terpotong):

.........................................
gnome-system-log                            2016-09-17 16:31:58.000000000 +0300
libyelp0                                    2016-09-17 16:32:00.000000000 +0300
gnome-system-monitor                        2016-09-17 16:32:00.000000000 +0300
yelp-xsl                                    2016-09-17 16:32:01.000000000 +0300
yelp                                        2016-09-17 16:32:03.000000000 +0300
gnome-user-guide                            2016-09-17 16:32:18.000000000 +0300
libapache2-mod-dnssd                        2016-09-17 16:32:19.000000000 +0300
.........................................
linux-compiler-gcc-4.8-x86                  2017-02-26 20:11:02.800756429 +0200
linux-headers-3.16.0-4-amd64                2017-02-26 20:11:10.463446327 +0200
linux-headers-3.16.0-4-common               2017-02-26 20:11:17.414555037 +0200
linux-libc-dev:amd64                        2017-02-26 20:11:21.126184016 +0200
openssl                                     2017-02-26 20:11:22.094098618 +0200
unzip                                       2017-02-26 20:11:23.118013331 +0200
wireless-regdb                              2017-02-26 20:11:23.929949143 +0200
nodejs                                      2017-02-26 20:11:33.321424052 +0200
nasm                                        2017-02-28 16:41:17.013509727 +0200
librecode0:amd64                            2017-03-01 10:38:49.817962640 +0200
libuchardet0                                2017-03-01 10:41:10.860098788 +0200
tree                                        2017-03-04 14:32:12.251787763 +0200
libtar0                                     2017-03-07 09:51:46.609746789 +0200
libtar-dev                                  2017-03-07 09:51:47.129753987 +0200

Cacat utama dari solusi ini adalah bahwa itu tidak teruji dengan baik dalam produksi.

PADYMKO
sumber
Ini adalah solusi indah yang hampir menyelesaikan pekerjaan. Ini hanya kekurangannya, apakah (1) ini sangat lambat dan (2) hanya muncul saat paket terakhir diperbarui , bukan versi sebelumnya. Ini, tentu saja bukan masalah one-liner, tetapi bagaimana dpkg tidak melacak sejarah /var/lib/dpkg/info/. Itu juga mengapa menggunakan /var/log/dpkg.log*mungkin lebih disukai.
not2qubit
1

Itu kasar, tetapi bekerja secepat solusi lain. Format tanggal adalah yyyymmddhhmmss, yang berarti bahwa sedikit atau pemesanan ulang dan memformat hasil penghapusan dalam angka yang dapat diurutkan.

Banyak terima kasih kepada solusi lain, daftar nama paket ini dalam urutan instalasi yang dapat digunakan dalam membangun untuk membuat sistem operasi salinan.

find /var/lib/dpkg/info -name "*.list" -exec stat -c $'%n\t%y' {} \; \
| sed -e 's,/var/lib/dpkg/info/,,' -e 's,\.list\t,\t,' \
| sort | awk '{print $2$3" "$1}' | sed '0,/RE/s/-//' \
| sed '0,/RE/s/-//' | sed '0,/RE/s/://' | sed '0,/RE/s/://' \
| sed '0,/RE/s/\\.//' | sed 's/:armhf//' | sort | awk '{print $2}'
Gua Alexander
sumber
Selamat datang di @ alexander-cave! Harap tambahkan beberapa baris output sehingga orang dapat melihat output seperti apa yang diharapkan.
not2qubit