- Removed Docker installation instructions from README.md as they are not yet functional. - Simplified the installation script by removing the upgrade process and directly checking for existing installations. - Added checks for required dependencies (python3, curl, python3-venv) during installation. - Improved logging throughout the application, replacing print statements with logger calls. - Enhanced email validation using regex and added error handling for invalid email addresses. - Updated the uninstall script to provide options for complete or partial removal of Vigil. - Created a logger service to handle logging to both console and log files. - Updated requirements.txt to use newer versions of dependencies. - Added versioning to the main application and provided a version option in the command line interface.
80 lines
2.6 KiB
Python
80 lines
2.6 KiB
Python
# _ __________________
|
|
# | | / / _/ ____/ _/ /
|
|
# | | / // // / __ / // /
|
|
# | |/ // // /_/ // // /___
|
|
# |___/___/\____/___/_____/
|
|
# © Uthmn 2025 under MIT license
|
|
|
|
import subprocess
|
|
from os import geteuid
|
|
import sys
|
|
import re
|
|
|
|
from services.logger import logger
|
|
|
|
def require_root():
|
|
if geteuid() != 0:
|
|
logger.error("This script requires root privileges. Please run with sudo.")
|
|
sys.exit(1)
|
|
|
|
def detect_apt():
|
|
try:
|
|
subprocess.run(["apt", "--version"], capture_output=True, text=True, check=True)
|
|
return True
|
|
except FileNotFoundError:
|
|
return False
|
|
except subprocess.CalledProcessError as e:
|
|
raise RuntimeError(f"Error running apt: {e.stderr or e}")
|
|
|
|
def check_updates():
|
|
# Update package list
|
|
try:
|
|
subprocess.run(["apt", "update"], capture_output=True, text=True, check=True, timeout=300)
|
|
except FileNotFoundError:
|
|
raise FileNotFoundError("apt not found on this system.")
|
|
except subprocess.CalledProcessError as e:
|
|
raise RuntimeError(f"Error running 'apt update': {e.stderr or e.stdout or e}")
|
|
|
|
# List upgradable packages
|
|
try:
|
|
result = subprocess.run(
|
|
["apt", "list", "--upgradable"],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
timeout=60,
|
|
)
|
|
upgrades = result.stdout.strip()
|
|
lines = [line for line in upgrades.splitlines() if line.strip()]
|
|
|
|
if len(lines) <= 1: # Only the header
|
|
return {} # No upgrades
|
|
|
|
package_dict = {}
|
|
for line in lines[1:]: # skip header
|
|
# Example line format:
|
|
# docker-ce/focal-security 5:24.0.1~3-0~ubuntu-focal amd64 [upgradable from: 5:23.0.0~3-0~ubuntu-focal]
|
|
match = re.match(
|
|
r"([^/]+)/([^\s]+)\s+([^\s]+)\s+[^\s]+\s+\[upgradable from: ([^\]]+)\]", line
|
|
)
|
|
if match:
|
|
name, repo, latest_version, installed_version = match.groups()
|
|
# Detect security update based on repo name containing "security"
|
|
is_security = "security" in repo.lower()
|
|
package_dict[name] = {
|
|
"installed_version": installed_version,
|
|
"latest_version": latest_version,
|
|
"repo": repo,
|
|
"security": is_security
|
|
}
|
|
return package_dict
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
raise RuntimeError(f"Error running 'apt list --upgradable': {e.stderr or e.stdout or e}")
|
|
|
|
if __name__ == "__main__":
|
|
require_root()
|
|
if detect_apt():
|
|
updates = check_updates()
|
|
logger.info(updates)
|