Is there any software that can help me reinstall software after fresh install
Save and restore all packages
On Debian/Ubuntu based systems you can dump the list of installed packages to a file
dpkg --get-selections > my_package_list.txt
and install them again by running
apt-cache dumpavail | sudo dpkg --merge-avail
sudo dpkg --set-selections < my_package_list.txt
sudo apt-get dselect-upgrade
The first line ensures dpkg
's database is up to date (nowadays most people use apt
to install packages which maintains its own database), the second line imports your saved selections and the third command installs the selected packages. See the Debian Administrator's Handbook for details.
In case you have installed packages from third-party repositories you need to add these repositories before following the above steps for restoring.
Save and restore only explicitly installed packages
Aptitude automatically installs dependencies (e.g. a library required by an application). These packages are flagged as "automatic" and can be automatically removed when they aren't required anymore. In case you want to preserve these "automatic" flags we can't use dpkg
since it doesn't track automatically installed packages. Instead we have to use the slightly more cryptic
LC_ALL=C aptitude search -F '%p %C' '~i!~M' > my_package_list.txt
This will search all packages that are installed (~i
) and not (!
) flagged automatic (~M
). For each matching package the package name (%p
) and the status (%C
) will be printed (this mimics the output of dpkg --get-selections
). LC_ALL=C
ensures that all output is done in English without translation to a native language. Use the commands mentioned above for installing the packages from this list. Refer to the aptitude user's manual for details.
Ansible is an open-source software provisioning, configuration management, and application-deployment tool. It runs on many Unix-like systems, and can configure both Unix-like systems as well as Microsoft Windows. It includes its own declarative language to describe system configuration
(From Wikipedia.) Homepage (Github).
There are several others in the same category. Reading about ansible should give you vocabulary to search for the others, and compare, if needed. Nix is a newer contender. Some say "more complex, but maybe just right.". chef is also on the scene.
Ansible example for hostname myhost
, module apt
(replace with yum
or whatever):
ansible -K -i myhost, -m apt -a "name=tcpdump,tmux state=present" --become myhost
The list "tcpdump,tmux" can be extended with commas. (The fact, that the hostname myhost
is twice in the command-line, because we are not using a fixed host inventory list, but an ad-hoc one, with the trailing comma.)
This only scratches the surface, Ansible has an extensive module collection.
If you just want to install a bunch of packages a simple one-liner could do like:
sudo bash -c 'for package in "tmux" "htop" "gimp"; do apt install -y --no-upgrade "$package"; done'
The loop is not strictly necessary, but without it, if apt fails to find any of the programs in the list, it will fail to install any of the other packages. This can happen for example if you switch to a more recent version of your distro and older packages are not within the repos anymore. If you prefer all or nothing use
sudo apt install -y --no-upgrade tmux htop gimp
If you also want to save your configurations the search term would be "dotfiles". Thats what the configurations in Unix like systems are called since they mostly start with a ".".
A quick and dirty way to save those is just by copying all those configurations directory to your new system. A better way would be to place them under version control with tools like git. I use a combination of git, dotbot and hand written scripts to setup my system.
Update
One point that is missing from the discussion so far is that apt
is typically not the only package management system one needs for anything beyond the bare basics.
Other package management tools might be snap
, pip
, conda
, cargo
and many more.
This is implicitly addressed in the answer by Alex Stragies. Ansible
contains a vast ammount of modules including modules to manage packages apart from apt
like snap
and pip
.
As my answer is focused on write-your-own-script I'd like to expand on that.
A well tested framework such as Ansible
should generally be prefered for most tasks, but self-written code gives an advantage in terms of flexibility in my eyes.
Small example framework
I've written a small code in python which shall examplify how such a framework could look.
#!/usr/bin/env python3
import os
import re
import sys
import subprocess
def read_package_list(path):
package_list=[]
try:
with open(os.path.realpath(path)) as f:
for line in f:
match = re.search(r'^(?!\s*$)(?!#)\w+',line)
if match:
package_list.append(match.group(0))
return package_list
except Exception as e:
print(e.message)
print(e.args)
sys.exit(1)
return package_list
def install_packages(command,package_list,err_log):
try:
with open(err_log,'w+') as f:
for p in package_list:
print('executing '+command+' '+str(p))
out=subprocess.run(command+' '+p,shell=True,stderr=f)
except Exception as e:
print(e.message)
print(e.args)
sys.exit(1)
def main():
args = sys.argv[1:]
package_list = read_package_list(args[1])
err_log=os.path.realpath(args[2])
install_packages(args[0],package_list,err_log)
if __name__ == '__main__':
main()
The basic ingredients are a function to process a list of packages separated by newlines (read_package_list
) and a function to execute the installer command in a shell (install_packages
).
Lines with only whitespace and lines starting with #
are ignored when reading in the package list.
The main
processes the arguments which can be given on the command line as installer command
, packagefile
, errorlog
.
What does that give me?
Well you can just use any installer command you like
./installerscript.py 'apt install --dry-run' myaptpackages.txt apt_err.log
./installerscript.py 'snap install' mysnaps.txt snap_err.log
./installerscript.py 'pip install --user' mypy.txt py_err.log
./installerscript.py 'git clone' repos.txt git_err.log
This might be helpful if one keeps a list of packages which should all be treated in the same way. Once such a framework exist it is easy to improve on it. One could, for example, customize the way the installation process is logged or customize the processing of the command line arguments. Another aspect is that the script probably shouldn't execute each command as root (if run as root) as it currently does.