When migrating Ubuntu servers, simply listing installed packages with dpkg -l
doesn't reveal the original installation context. We need to distinguish between:
- Manually installed packages (explicit user commands)
- Automatically installed dependencies
- Default system packages
The simplest approach examines bash history:
cat ~/.bash_history | grep "apt-get install"
# Or for root commands:
sudo cat /root/.bash_history | grep "apt-get install"
Limitations:
- History gets rotated/truncated
- Doesn't capture installations via GUI tools
- Misses commands run in other shells
More reliable approach using APT's built-in logging:
grep "install " /var/log/apt/history.log
# For comprehensive output including timestamps:
zcat /var/log/apt/history.log.*.gz | grep "install "
Create an installation script from your history:
grep -h "Commandline: apt-get install" /var/log/apt/history.log* \
| sed 's/Commandline: //' \
| sort -u > install_history.sh
For understanding package relationships:
aptitude search '~i!~M' # Shows manually installed packages
aptitude why <package> # Shows why a package was installed
Complete solution for server migration:
#!/bin/bash
# Get all manually installed packages
apt-mark showmanual > manual-pkgs.txt
# Generate installation commands
echo "#!/bin/bash" > migrate.sh
awk '{print "sudo apt-get install -y " $0}' manual-pkgs.txt >> migrate.sh
chmod +x migrate.sh
For future reference, consider version controlling your package state:
apt list --installed > packages.list
git add packages.list
git commit -m "Snapshot of installed packages"
When migrating Ubuntu servers, one critical task is replicating the exact software environment from the old system to the new one. While dpkg -l
lists installed packages, it doesn't distinguish between manually installed packages and automatically installed dependencies.
Ubuntu maintains detailed installation logs that can be accessed through:
cat /var/log/apt/history.log
# For compressed historical logs:
zcat /var/log/apt/history.log.*.gz
This will show entries like:
Commandline: apt-get install nginx
Install: libnginx-mod-http-geoip:amd64 (1.18.0-0ubuntu1), nginx-common:amd64 (1.18.0-0ubuntu1), nginx-core:amd64 (1.18.0-0ubuntu1)
To get specifically the packages you explicitly installed (excluding dependencies):
comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort -u)
For understanding which packages pulled in dependencies:
apt-cache depends --installed --recurse PACKAGE_NAME | grep -v " " | sort -u
Here's a complete bash script to generate an installation script for your new server:
#!/bin/bash
# Generate installation script from APT history
OUTFILE="migration_install.sh"
echo "#!/bin/bash" > $OUTFILE
echo "# Auto-generated package installation script" >> $OUTFILE
echo "sudo apt-get update" >> $OUTFILE
zgrep -h "Commandline: apt-get install" /var/log/apt/history.log* | \
sed 's/Commandline: apt-get install/sudo apt-get install -y/' | \
sort -u >> $OUTFILE
chmod +x $OUTFILE
echo "Generated installation script: $OUTFILE"
For more advanced scenarios, examine the package states:
grep -B1 "Automatically installed" /var/lib/apt/extended_states || \
echo "No automatically installed packages found"
- Logs rotate and older entries may be compressed or deleted
- Consider using
aptitude
instead of apt-get for better tracking - For production systems, consider using configuration management tools like Ansible