Uncover the infinite in IT

Table of Contents
< All Topics

Automated Package Management

1) How to Create and Run the Python Script:

Step 1: Create the Python Script

Create a new file with a .py extension, e.g., apt.py. Copy and paste the following script into this file.

import os
import subprocess

# Get the current username
username = os.getenv("USER")

# Get the path to the servers list file in the same directory as the script
script_directory = os.path.dirname(os.path.abspath(__file__))
servers_list_default = "servers.list"

# Ask the user for the host list file
deployment_choice = input("Deploy to a single host or a host list?\n1) single host\n2) host list\nEnter the number of your choice: ").lower()

if deployment_choice == "1":
    # Ask the user for the IP of the single host
    target_host = input("Enter the IP of the host to deploy to: ")
    target_hosts = [target_host]

elif deployment_choice == "2":
    # Ask the user for the name of the servers' list file
    servers_list_custom = input(f"Enter the name of the servers' list file (default: {servers_list_default}): ")
    servers_list = servers_list_custom if servers_list_custom else servers_list_default

    # Use the specified servers' list file to get the list of hosts
    servers_list_path = os.path.join(script_directory, servers_list)
    if not os.path.exists(servers_list_path):
        print(f"Error: The specified servers' list file '{servers_list}' does not exist.")
        exit(1)

    with open(servers_list_path, 'r') as file:
        target_hosts = file.read().splitlines()

else:
    print("Invalid choice. Please enter either '1' for a single host or '2' for a host list.")
    exit(1)

# Ask the user for the action to perform (only once for the entire host list)
action_choice = input(
    "What action do you want performed?\n1) update & upgrade\n2) install\n3) remove\n4) purge\nEnter the number of your choice: ").lower()

if action_choice not in ["1", "2", "3", "4"]:
    print("Invalid choice. Please enter a number between 1 and 4.")
    exit(1)

# Loop through each target host
for server in target_hosts:
    try:
        # Get the remote server's hostname using port 22
        remote_hostname_result = subprocess.run(
            ["ssh", "-p", "22", "-o", "StrictHostKeyChecking=no", f"{username}@{server}", "hostname"],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE
        )
        remote_hostname = remote_hostname_result.stdout.decode().strip()

        print(f"Connecting to {remote_hostname} on port 22...")

        # Apply the action based on the user's choice
        if action_choice == "1":
            subprocess.run(
                ["ssh", "-A", "-p", "22", "-o", "StrictHostKeyChecking=no", f"{username}@{server}",
                 "sudo apt update && sudo apt upgrade -y"],
                check=True
            )
            print(f"Successfully performed 'apt update && apt upgrade' on {remote_hostname}.")

        elif action_choice == "2":
            package_to_install = input("Enter the package name to install: ")
            subprocess.run(
                ["ssh", "-A", "-p", "22", "-o", "StrictHostKeyChecking=no", f"{username}@{server}",
                 f"sudo apt install {package_to_install} -y"],
                check=True
            )
            print(f"Successfully installed '{package_to_install}' on {remote_hostname}.")

        elif action_choice == "3":
            package_to_remove = input("Enter the package name to remove: ")
            subprocess.run(
                ["ssh", "-A", "-p", "22", "-o", "StrictHostKeyChecking=no", f"{username}@{server}",
                 f"sudo apt remove {package_to_remove} -y"],
                check=True
            )
            print(f"Successfully removed '{package_to_remove}' from {remote_hostname}.")

        elif action_choice == "4":
            package_to_purge = input("Enter the package name to purge: ")
            subprocess.run(
                ["ssh", "-A", "-p", "22", "-o", "StrictHostKeyChecking=no", f"{username}@{server}",
                 f"sudo apt purge {package_to_purge} -y"],
                check=True
            )
            print(f"Successfully purged '{package_to_purge}' from {remote_hostname}.")

        # Disconnect from SSH using port 22
        subprocess.run(["ssh", "-A", "-p", "22", "-o", "StrictHostKeyChecking=no", f"{username}@{server}", "exit"])
        print(f"Disconnected from {remote_hostname}.")

    except subprocess.CalledProcessError as e:
        print(f"Failed to connect to {server} on port 22. Trying port 2022...")

        try:
            # Get the remote server's hostname using port 2022
            remote_hostname_result = subprocess.run(
                ["ssh", "-p", "2022", "-o", "StrictHostKeyChecking=no", f"{username}@{server}", "hostname"],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )
            remote_hostname = remote_hostname_result.stdout.decode().strip()

            print(f"Connecting to {remote_hostname} on port 2022...")

            # Apply the action based on the user's choice
            if action_choice == "1":
                subprocess.run(
                    ["ssh", "-A", "-p", "2022", "-o", "StrictHostKeyChecking=no", f"{username}@{server}",
                     "sudo apt update && sudo apt upgrade -y"],
                    check=True
                )
                print(f"Successfully performed 'apt update && apt upgrade' on {remote_hostname}.")

            elif action_choice == "2":
                package_to_install = input("Enter the package name to install: ")
                subprocess.run(
                    ["ssh", "-A", "-p", "2022", "-o", "StrictHostKeyChecking=no", f"{username}@{server}",
                     f"sudo apt install {package_to_install} -y"],
                    check=True
                )
                print(f"Successfully installed '{package_to_install}' on {remote_hostname}.")

            elif action_choice == "3":
                package_to_remove = input("Enter the package name to remove: ")
                subprocess.run(
                    ["ssh", "-A", "-p", "2022", "-o", "StrictHostKeyChecking=no", f"{username}@{server}",
                     f"sudo apt remove {package_to_remove} -y"],
                    check=True
                )
                print(f"Successfully removed '{package_to_remove}' from {remote_hostname}.")

            elif action_choice == "4":
                package_to_purge = input("Enter the package name to purge: ")
                subprocess.run(
                    ["ssh", "-A", "-p", "2022", "-o", "StrictHostKeyChecking=no", f"{username}@{server}",
                     f"sudo apt purge {package_to_purge} -y"],
                    check=True
                )
                print(f"Successfully purged '{package_to_purge}' from {remote_hostname}.")

            # Disconnect from SSH using port 2022
            subprocess.run(["ssh", "-A", "-p", "2022", "-o", "StrictHostKeyChecking=no", f"{username}@{server}", "exit"])
            print(f"Disconnected from {remote_hostname} on port 2022.")

        except subprocess.CalledProcessError as e:
            print(f"Failed to connect to {server} on port 2022. Error: {e}")
        except Exception as e:
            print(f"Failed to execute the chosen action on {remote_hostname}: {e}")

    except Exception as e:
        print(f"Failed to execute the chosen action on {remote_hostname}: {e}")

Step 2: Save the File

Save the file after pasting the script.

Step 3: Open a Terminal

Open a terminal on your computer.

Step 4: Navigate to the Script’s Directory

Use the cd command to navigate to the directory where your Python script is saved.

Step 5: Run the Script

Run the script using the command:

python3 apt.py

or

python apt.py

2) What It Does:

The script automates package management tasks on remote servers using SSH. It supports the following actions:

  • Update and upgrade packages (apt update && apt upgrade -y)
  • Install a specified package
  • Remove a specified package
  • Purge a specified package

3) Example Output for Every Interactive Step Taken:

Example Output – Choosing Deployment Type:

Deploy to a single host or a host list?
1) single host
2) host list
Enter the number of your choice: 1

Example Output – Entering Single Host IP:

Enter the IP of the host to deploy to: 10.0.1.234

Example Output – Choosing Action:

What action do you want performed?
1) update & upgrade
2) install
3) remove
4) purge
Enter the number of your choice: 1

Example Output – Performing Action on Single Host:

Connecting to [hostname] on port 22...

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Hit:1 http://security.debian.org bullseye-security InRelease
Hit:2 http://deb.debian.org/debian bullseye InRelease
Hit:3 http://deb.debian.org/debian bullseye-updates InRelease
Hit:4 https://repo.zabbix.com/zabbix/6.4/debian bullseye InRelease
Reading package lists...
Building dependency tree...
Reading state information...
All packages are up to date.

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
Building dependency tree...
Reading state information...
Calculating upgrade...
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Successfully performed 'apt update && apt upgrade' on [hostname].
Disconnected from [hostname].

Example Output – Choosing Action for Multiple Hosts:

Do you want to perform the action on a single host or multiple hosts?
1) single host
2) multiple hosts
Enter the number of your choice: 2

Example Output – Entering Host List File:

Enter the name of the servers' list file (default: servers.list): targets.list
Connecting to [hostname1] on port 22...

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Hit:1 http://deb.debian.org/debian bullseye InRelease
Hit:2 http://security.debian.org bullseye-security InRelease
Hit:3 https://downloads.plex.tv/repo/deb public InRelease
Hit:4 http://deb.debian.org/debian bullseye-updates InRelease
Hit:5 https://repo.zabbix.com/zabbix/6.4/debian bullseye InRelease
Reading package lists...
Building dependency tree...
Reading state information...
All packages are up to date.

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
Building dependency tree...
Reading state information...
Calculating upgrade...
0 upgraded, 0 newly installed, 0 to remove, and 0 not upgraded.
Successfully performed 'apt update && apt upgrade' on [hostname1].
Disconnected from [hostname1] on port 22.

Connecting to  on port 22...
ssh: connect to host [hostname2] port 22: Connection refused
Failed to connect to [hostname2] on port 22. Trying port 2022...
Connecting to [hostname2] on port 2022...

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Hit:1 http://deb.debian.org/debian bullseye InRelease
Hit:2 http://security.debian.org bullseye-security InRelease
Hit:3 https://downloads.plex.tv/repo/deb public InRelease
Hit:4 http://deb.debian.org/debian bullseye-updates InRelease
Hit:5 https://repo.zabbix.com/zabbix/6.4/debian bullseye InRelease
Reading package lists...
Building dependency tree...
Reading state information...
All packages are up to date.

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
Building dependency tree...
Reading state information...
Calculating upgrade...
0 upgraded, 0 newly installed, 0 to remove, and 0 not upgraded.
Successfully performed 'apt update && apt upgrade' on [hostname2].
Disconnected from [hostname2] on port 2022.

This guide provides a step-by-step process for creating, running, and understanding the output of the Python script. Adjustments may be needed based on specific system configurations.