5

Given two machines:

  • ServerA
  • ServerB

which tool best outputs a "set", diff-like view of packages installed:

  • Only on ServerA
  • Only on ServerB
  • On both machines

2 Answers 2

8

I just coded this script, which compares also package versions (if you don't need versions, then what ændrük posted is better):

https://github.com/lepe/scripts/blob/master/compare_ubuntu_apt.pl

Usage:

1) Generate package list in both computers, like:

apt --installed list | tail -n+2 > that_server.lst

2) Execute the perl script:

./compare_ubuntu_apt.pl this_server.lst that_server.lst

Results: (example)

----------------------------------
 DIFFERENCES 
----------------------------------
 @ apparmor : 2.8.95~2430-0ubuntu5.2 -> 2.8.95~2430-0ubuntu5.3
 @ apt : 1.0.1ubuntu2.8 -> 1.0.1ubuntu2.10
 @ apt-transport-https : 1.0.1ubuntu2.8 -> 1.0.1ubuntu2.10
 @ apt-utils : 1.0.1ubuntu2.8 -> 1.0.1ubuntu2.10
 @ base-files : 7.2ubuntu5.2 -> 7.2ubuntu5.3
 @ bash-completion : 1:2.1-4 -> 1:2.1-4ubuntu0.1
----------------------------------
 MISSING IN this_server.lst
----------------------------------
 + acl : 2.2.52-1
 + acpid : 1:2.0.21-1ubuntu2
 + apport : 2.14.1-0ubuntu3.11
 + apport-symptoms : 0.20
 + at : 3.1.14-1ubuntu1
 + at-spi2-core : 2.10.2.is.2.10.1-0ubuntu1
 + attr : 1:2.4.47-1ubuntu1
 + autotools-dev : 20130810.1
----------------------------------
 MISSING IN that_server.lst
----------------------------------
 - apcupsd : 3.14.10-2build1
 - apcupsd-doc : 3.14.10-2build1
 - beep : 1.3-3
 - btrfs-tools : 3.12-1
 - discover : 2.1.2-5.2ubuntu1
2
  • Your script doesn't seems to work for me: I get this::::: Use of uninitialized value $missing{"\n"} in concatenation (.) or string at ./compare_apt.pl line 82. - :
    – V. Sambor
    Apr 10, 2020 at 9:09
  • I updated the script. It seems that the second list passed as argument contained an unexpected new line character. Now it should work fine.
    – lepe
    Apr 11, 2020 at 2:46
7
  1. Get the list of all packages for each machine as text files:

    $ ssh server-a dpkg --get-selections | grep '\binstall$' | cut -f 1 > server-a.txt
    $ ssh server-b dpkg --get-selections | grep '\binstall$' | cut -f 1 > server-b.txt
    
  2. Use shell "set operations" to generate the desired results:

    $ comm -12 <(sort server-a.txt) <(sort server-b.txt) > both.txt
    $ comm -23 <(sort server-a.txt) <(sort server-b.txt) > only-server-a.txt
    $ comm -13 <(sort server-a.txt) <(sort server-b.txt) > only-server-b.txt
    
  3. Review how many packages are in each set:

    $ wc -l *.txt
      2238 both.txt
       948 only-server-a.txt
        89 only-server-b.txt
      3186 server-a.txt
      2327 server-b.txt
      8788 total
    
3
  • Note that no space between the < and ( is important for #2 to work properly.
    – Randall
    Mar 18, 2016 at 2:32
  • Here is another similar way using diff. Sep 23, 2017 at 15:40
  • Updated link for using diff
    – malhal
    Jul 21, 2023 at 20:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .