Refactor installation and uninstallation scripts; enhance logging and error handling
- 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.
This commit is contained in:
parent
a08228f7ef
commit
312d3e9674
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"idf.pythonInstallPath": "/usr/bin/python3"
|
||||
}
|
||||
22
README.md
22
README.md
@ -13,8 +13,6 @@ Vigil is designed for stability and security, avoiding keeping credentials in th
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Installation and Running](#installation-and-running)
|
||||
- [Installation](#installation)
|
||||
- [Using the install script (recommended)](#using-the-install-script-recommended)
|
||||
- [Using Docker](#using-docker)
|
||||
- [Usage](#usage)
|
||||
- [Running Vigil](#running-vigil)
|
||||
- [1. Scheduled Mode (serve)](#1-scheduled-mode-serve)
|
||||
@ -91,8 +89,6 @@ This will check for updates every hour and send an email to the provided email a
|
||||
|
||||
## Installation
|
||||
|
||||
### Using the install script (recommended)
|
||||
|
||||
The easiest way to install Vigil is by using the interactive install script.
|
||||
This script automatically checks for required dependencies, offers to install any that are missing, and can optionally configure Vigil to start automatically on boot via **systemd**.
|
||||
|
||||
@ -126,24 +122,6 @@ sudo bash uninstall.sh
|
||||
rm uninstall.sh
|
||||
```
|
||||
|
||||
### Using docker
|
||||
|
||||
> [!WARNING]
|
||||
> The docker run command will not work yet and needs to be updated when released.
|
||||
> The docker section will also be updated to include compose examples.
|
||||
|
||||
If you prefer to use Docker, you can download the latest Docker image from the [Docker Hub](https://hub.docker.com/r/uthmn/vigil)
|
||||
|
||||
```bash
|
||||
docker pull uthmn/vigil
|
||||
```
|
||||
|
||||
You can now run Vigil using the following command:
|
||||
|
||||
```bash
|
||||
docker run -it --rm uthmn/vigil
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Once installed, Vigil can be run in two modes:
|
||||
|
||||
426
install.sh
426
install.sh
@ -10,75 +10,23 @@ fi
|
||||
ACTUAL_USER=${SUDO_USER:-$USER}
|
||||
USER_HOME=$(eval echo ~$ACTUAL_USER)
|
||||
|
||||
# Now check if we already have vigil installed
|
||||
if [[ -d "/opt/vigil" ]]; then
|
||||
echo "Vigil is already installed."
|
||||
echo "Would you like to upgrade? This will preserve your .env and users.json files. (y/n)"
|
||||
read -r answer
|
||||
# /opt/vigil = static files/code
|
||||
# /etc/vigil = configurations
|
||||
# /var/log/vigil = logs
|
||||
|
||||
if [[ "${answer,,}" == "y" ]]; then
|
||||
echo "Backing up configuration files..."
|
||||
|
||||
# Create temporary backup directory
|
||||
BACKUP_DIR="/tmp/vigil_backup_$(date +%s)"
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# Backup .env and users.json if they exist
|
||||
if [[ -f "/opt/vigil/.env" ]]; then
|
||||
cp /opt/vigil/.env "$BACKUP_DIR/.env"
|
||||
echo "Backed up .env"
|
||||
fi
|
||||
|
||||
if [[ -f "/opt/vigil/users.json" ]]; then
|
||||
cp /opt/vigil/users.json "$BACKUP_DIR/users.json"
|
||||
echo "Backed up users.json"
|
||||
fi
|
||||
|
||||
# Stop the service if it's running
|
||||
if systemctl is-active --quiet vigil.service; then
|
||||
echo "Stopping vigil service..."
|
||||
systemctl stop vigil.service
|
||||
fi
|
||||
|
||||
# Remove the old installation
|
||||
echo "Removing old installation..."
|
||||
rm -rf /opt/vigil
|
||||
|
||||
echo "Upgrade preparation complete. Proceeding with fresh installation..."
|
||||
echo ""
|
||||
|
||||
# Set flag to restore config later
|
||||
UPGRADE_MODE=true
|
||||
else
|
||||
echo "Installation cancelled. Please remove /opt/vigil manually if you want a fresh install."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Now check if we are running on a supported system
|
||||
# Check if we are running on a supported system
|
||||
if [[ "$OSTYPE" != "linux-gnu"* ]]; then
|
||||
echo "This script is only supported on Linux" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if we have apt installed
|
||||
# Now check if we have apt installed
|
||||
if ! command -v apt &> /dev/null; then
|
||||
echo "Apt is not installed. Please install it before running this script." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Now check if we have git and python3 installed, if not offer to install them
|
||||
if ! command -v git &> /dev/null; then
|
||||
echo "Git is not installed. Do you want to install it now? (y/n)"
|
||||
read -r answer
|
||||
if [[ "${answer,,}" == "y" ]]; then
|
||||
apt install git -y
|
||||
else
|
||||
echo "Please install git before running this script." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Now check if we have python3 installed, if not offer to install it
|
||||
if ! command -v python3 &> /dev/null; then
|
||||
echo "Python 3 is not installed. Do you want to install it now? (y/n)"
|
||||
read -r answer
|
||||
@ -90,7 +38,19 @@ if ! command -v python3 &> /dev/null; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Now check if we have python3 -m pip installed, if not offer to install it
|
||||
# Now check if we have curl installed, if not offer to install it
|
||||
if ! command -v curl &> /dev/null; then
|
||||
echo "Curl is not installed. Do you want to install it now? (y/n)"
|
||||
read -r answer
|
||||
if [[ "${answer,,}" == "y" ]]; then
|
||||
apt install curl -y
|
||||
else
|
||||
echo "Please install curl before running this script." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Now check if we have python3-pip installed, if not offer to install it
|
||||
if ! python3 -m pip --version &> /dev/null; then
|
||||
echo "pip is not installed. Do you want to install it now? (y/n)"
|
||||
read -r answer
|
||||
@ -102,12 +62,76 @@ if ! python3 -m pip --version &> /dev/null; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Now git clone the repository to /opt/vigil
|
||||
echo ""
|
||||
echo "Cloning Vigil repository..."
|
||||
git clone https://git.uthmn.com/ufatih/vigil.git /opt/vigil
|
||||
# Now check if we have python3-venv installed, if not offer to install it
|
||||
if ! python3 -m venv &> /dev/null; then
|
||||
echo "Python3-venv is not installed. Do you want to install it now? (y/n)"
|
||||
read -r answer
|
||||
if [[ "${answer,,}" == "y" ]]; then
|
||||
apt install python3-venv -y
|
||||
else
|
||||
echo "Please install python3-venv before running this script." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Now create a virtual environment and install the required packages
|
||||
if [[ -d "/opt/vigil" ]]; then
|
||||
echo "Vigil is already installed."
|
||||
echo "Would you like to upgrade? This will preserve your configuration. (y/n)"
|
||||
read -r answer
|
||||
|
||||
if [[ "${answer,,}" == "y" ]]; then
|
||||
echo "Stopping vigil service..."
|
||||
systemctl stop vigil 2>/dev/null
|
||||
echo "Removing old installation..."
|
||||
rm -rf /opt/vigil
|
||||
# Continue with installation
|
||||
else
|
||||
echo "Installation cancelled."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# First create the required directories
|
||||
echo ""
|
||||
# Creating the /opt/vigil directory
|
||||
echo "Creating /opt/vigil directory..."
|
||||
mkdir -p /opt/vigil
|
||||
# Create the /opt/vigil/services directory
|
||||
echo "Creating /opt/vigil/services directory..."
|
||||
mkdir -p /opt/vigil/services
|
||||
# Create the /etc/vigil directory
|
||||
echo "Creating /etc/vigil directory..."
|
||||
mkdir -p /etc/vigil
|
||||
# Create the /var/log/vigil directory
|
||||
echo "Creating /var/log/vigil directory..."
|
||||
mkdir -p /var/log/vigil
|
||||
|
||||
# Now curl -fsSL each file into the /opt/vigil directory
|
||||
curl -fsSL https://git.uthmn.com/ufatih/vigil/raw/branch/main/LICENSE -o /opt/vigil/LICENSE || { echo "Failed to download LICENSE file."; exit 1; }
|
||||
echo " ✓ LICENSE"
|
||||
curl -fsSL https://git.uthmn.com/ufatih/vigil/raw/branch/main/README.md -o /opt/vigil/README.md || { echo "Failed to download README.md file."; exit 1; }
|
||||
echo " ✓ README.md"
|
||||
curl -fsSL https://git.uthmn.com/ufatih/vigil/raw/branch/main/install.sh -o /opt/vigil/install.sh || { echo "Failed to download install.sh file."; exit 1; }
|
||||
echo " ✓ install.sh"
|
||||
curl -fsSL https://git.uthmn.com/ufatih/vigil/raw/branch/main/uninstall.sh -o /opt/vigil/uninstall.sh || { echo "Failed to download uninstall.sh file."; exit 1; }
|
||||
echo " ✓ uninstall.sh"
|
||||
curl -fsSL https://git.uthmn.com/ufatih/vigil/raw/branch/main/requirements.txt -o /opt/vigil/requirements.txt || { echo "Failed to download requirements.txt file."; exit 1; }
|
||||
echo " ✓ requirements.txt"
|
||||
|
||||
curl -fsSL https://git.uthmn.com/ufatih/vigil/raw/branch/main/main.py -o /opt/vigil/main.py || { echo "Failed to download main.py file."; exit 1; }
|
||||
echo " ✓ main.py"
|
||||
curl -fsSL https://git.uthmn.com/ufatih/vigil/raw/branch/main/services/apt.py -o /opt/vigil/services/apt.py || { echo "Failed to download services/apt.py file."; exit 1; }
|
||||
echo " ✓ services/apt.py"
|
||||
curl -fsSL https://git.uthmn.com/ufatih/vigil/raw/branch/main/services/mail.py -o /opt/vigil/services/mail.py || { echo "Failed to download services/mail.py file."; exit 1; }
|
||||
echo " ✓ services/mail.py"
|
||||
curl -fsSL https://git.uthmn.com/ufatih/vigil/raw/branch/main/services/logger.py -o /opt/vigil/services/logger.py || { echo "Failed to download services/logger.py file."; exit 1; }
|
||||
echo " ✓ services/logger.py"
|
||||
curl -fsSL https://git.uthmn.com/ufatih/vigil/raw/branch/main/services/__init__.py -o /opt/vigil/services/__init__.py || { echo "Failed to download services/__init__.py file."; exit 1; }
|
||||
echo " ✓ services/__init__.py"
|
||||
|
||||
echo "✓ All files downloaded successfully"
|
||||
|
||||
# Now create a venv and install the required packages
|
||||
echo ""
|
||||
echo "Setting up virtual environment and installing dependencies..."
|
||||
python3 -m venv /opt/vigil/.venv
|
||||
@ -115,221 +139,18 @@ source /opt/vigil/.venv/bin/activate
|
||||
pip install -r /opt/vigil/requirements.txt
|
||||
deactivate
|
||||
|
||||
# Now create a .env file and request the user to fill in the required values
|
||||
echo ""
|
||||
echo "=== Email Configuration ==="
|
||||
echo ""
|
||||
# Create a systemd service
|
||||
|
||||
# Check if we're in upgrade mode and have a backup
|
||||
if [[ "$UPGRADE_MODE" == true ]] && [[ -f "$BACKUP_DIR/.env" ]]; then
|
||||
echo "Found existing .env configuration. Would you like to:"
|
||||
echo "1) Keep existing configuration"
|
||||
echo "2) Enter new configuration"
|
||||
read -r config_choice
|
||||
|
||||
if [[ "$config_choice" == "1" ]]; then
|
||||
cp "$BACKUP_DIR/.env" /opt/vigil/.env
|
||||
echo "Restored existing .env configuration"
|
||||
chmod 600 /opt/vigil/.env
|
||||
|
||||
# Skip to connection testing
|
||||
SKIP_ENV_INPUT=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$SKIP_ENV_INPUT" != true ]]; then
|
||||
touch /opt/vigil/.env
|
||||
|
||||
# SMTP settings
|
||||
echo "Please enter SMTP server address:"
|
||||
read -r SMTP_SERVER
|
||||
|
||||
echo "Please enter SMTP port (default: 587 for TLS, 465 for SSL):"
|
||||
read -r SMTP_PORT
|
||||
|
||||
echo "Please enter SMTP username:"
|
||||
read -r SMTP_USERNAME
|
||||
|
||||
echo "Please enter SMTP password:"
|
||||
read -rs SMTP_PASSWORD
|
||||
echo ""
|
||||
|
||||
# IMAP settings
|
||||
echo "Please enter IMAP server address:"
|
||||
read -r IMAP_SERVER
|
||||
|
||||
echo "Please enter IMAP port (default: 993 for SSL):"
|
||||
read -r IMAP_PORT
|
||||
|
||||
echo "Please enter IMAP username:"
|
||||
read -r IMAP_USERNAME
|
||||
|
||||
echo "Please enter IMAP password:"
|
||||
read -rs IMAP_PASSWORD
|
||||
echo ""
|
||||
|
||||
# Write to .env file
|
||||
cat > /opt/vigil/.env << EOF
|
||||
SMTP_SERVER=$SMTP_SERVER
|
||||
SMTP_PORT=$SMTP_PORT
|
||||
SMTP_USERNAME=$SMTP_USERNAME
|
||||
SMTP_PASSWORD=$SMTP_PASSWORD
|
||||
|
||||
IMAP_SERVER=$IMAP_SERVER
|
||||
IMAP_PORT=$IMAP_PORT
|
||||
IMAP_USERNAME=$IMAP_USERNAME
|
||||
IMAP_PASSWORD=$IMAP_PASSWORD
|
||||
EOF
|
||||
|
||||
echo "Configuration saved to /opt/vigil/.env"
|
||||
|
||||
# Set secure permissions on .env file (contains passwords)
|
||||
chmod 600 /opt/vigil/.env
|
||||
fi
|
||||
|
||||
# Test if the inputs work/are valid, else tell the user to fill in later and continue
|
||||
if [[ "$SKIP_ENV_INPUT" != true ]]; then
|
||||
echo ""
|
||||
echo "Testing connections..."
|
||||
|
||||
# Check if required commands are available
|
||||
if command -v nc >/dev/null 2>&1; then
|
||||
# Test SMTP connection with netcat (timeout after 5 seconds)
|
||||
echo "Testing SMTP connection to $SMTP_SERVER:$SMTP_PORT..."
|
||||
if timeout 5 nc -zv "$SMTP_SERVER" "$SMTP_PORT" 2>&1 | grep -q succeeded; then
|
||||
echo "[OK] SMTP connection successful"
|
||||
SMTP_VALID=true
|
||||
else
|
||||
echo "[FAILED] SMTP connection failed - could not reach $SMTP_SERVER:$SMTP_PORT"
|
||||
SMTP_VALID=false
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Test IMAP connection
|
||||
echo "Testing IMAP connection to $IMAP_SERVER:$IMAP_PORT..."
|
||||
if timeout 5 nc -zv "$IMAP_SERVER" "$IMAP_PORT" 2>&1 | grep -q succeeded; then
|
||||
echo "[OK] IMAP connection successful"
|
||||
IMAP_VALID=true
|
||||
else
|
||||
echo "[FAILED] IMAP connection failed - could not reach $IMAP_SERVER:$IMAP_PORT"
|
||||
IMAP_VALID=false
|
||||
fi
|
||||
else
|
||||
echo "[WARNING] Cannot test connections (nc not installed). Skipping validation."
|
||||
SMTP_VALID=unknown
|
||||
IMAP_VALID=unknown
|
||||
fi
|
||||
|
||||
# Summary and continue
|
||||
echo ""
|
||||
if [ "$SMTP_VALID" = false ] || [ "$IMAP_VALID" = false ]; then
|
||||
echo "[WARNING] Some connections failed."
|
||||
echo "Configuration has been saved to /opt/vigil/.env"
|
||||
echo "Please verify your settings and update the file manually if needed."
|
||||
echo ""
|
||||
read -p "Press Enter to continue..." -r
|
||||
else
|
||||
echo "[OK] All connections successful!"
|
||||
echo "Configuration saved to /opt/vigil/.env"
|
||||
fi
|
||||
else
|
||||
echo ""
|
||||
echo "[OK] Using existing email configuration"
|
||||
fi
|
||||
|
||||
# Now create a users.json file and request the user to fill in the required values (or leave empty to skip)
|
||||
echo ""
|
||||
echo "=== Notification Recipients ==="
|
||||
echo ""
|
||||
|
||||
# Check if we're in upgrade mode and have a backup
|
||||
if [[ "$UPGRADE_MODE" == true ]] && [[ -f "$BACKUP_DIR/users.json" ]]; then
|
||||
echo "Found existing users.json configuration. Would you like to:"
|
||||
echo "1) Keep existing recipients"
|
||||
echo "2) Enter new recipients"
|
||||
read -r users_choice
|
||||
|
||||
if [[ "$users_choice" == "1" ]]; then
|
||||
cp "$BACKUP_DIR/users.json" /opt/vigil/users.json
|
||||
echo "Restored existing notification recipients"
|
||||
|
||||
# Clean up backup directory
|
||||
rm -rf "$BACKUP_DIR"
|
||||
|
||||
# Skip to next section
|
||||
SKIP_USERS_INPUT=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$SKIP_USERS_INPUT" != true ]]; then
|
||||
echo "Please enter the email addresses vigil will send notifications to (comma separated):"
|
||||
echo "(Leave empty to skip)"
|
||||
read -r EMAILS
|
||||
|
||||
# Strip whitespace and convert to JSON array
|
||||
if [ -n "$EMAILS" ]; then
|
||||
# Remove all whitespace, split by comma, and build JSON array
|
||||
EMAILS_CLEAN=$(echo "$EMAILS" | tr -d '[:space:]')
|
||||
|
||||
# Convert to JSON array format
|
||||
EMAILS_JSON="["
|
||||
IFS=',' read -ra EMAIL_ARRAY <<< "$EMAILS_CLEAN"
|
||||
for i in "${!EMAIL_ARRAY[@]}"; do
|
||||
if [ $i -gt 0 ]; then
|
||||
EMAILS_JSON="$EMAILS_JSON,"
|
||||
fi
|
||||
EMAILS_JSON="$EMAILS_JSON\"${EMAIL_ARRAY[$i]}\""
|
||||
done
|
||||
EMAILS_JSON="$EMAILS_JSON]"
|
||||
|
||||
echo "$EMAILS_JSON" > /opt/vigil/users.json
|
||||
echo "Notification recipients saved to /opt/vigil/users.json"
|
||||
else
|
||||
echo "[]" > /opt/vigil/users.json
|
||||
echo "No recipients configured. You can add them later in /opt/vigil/users.json"
|
||||
fi
|
||||
|
||||
# Clean up backup directory if it exists
|
||||
if [[ -n "$BACKUP_DIR" ]] && [[ -d "$BACKUP_DIR" ]]; then
|
||||
rm -rf "$BACKUP_DIR" # Don't want to hit a steam
|
||||
fi
|
||||
fi
|
||||
|
||||
# Set ownership of vigil directory to actual user
|
||||
chown -R "$ACTUAL_USER:$ACTUAL_USER" /opt/vigil
|
||||
|
||||
# Create the alias to the command
|
||||
echo ""
|
||||
echo "Adding 'vigil' command alias..."
|
||||
ALIAS_LINE="alias vigil='source /opt/vigil/.venv/bin/activate && python3 /opt/vigil/main.py && deactivate'"
|
||||
|
||||
# Add to user's bashrc if not already present
|
||||
if ! grep -q "alias vigil=" "$USER_HOME/.bashrc" 2>/dev/null; then
|
||||
echo "$ALIAS_LINE" >> "$USER_HOME/.bashrc"
|
||||
echo "Alias added to $USER_HOME/.bashrc"
|
||||
else
|
||||
echo "Alias already exists in $USER_HOME/.bashrc"
|
||||
fi
|
||||
|
||||
# Suggest to add vigil to systemctl to autostart (after network is up)
|
||||
echo ""
|
||||
echo "Would you like to add vigil to autostart on boot? (y/n)"
|
||||
read -r answer
|
||||
if [[ "${answer,,}" == "y" ]]; then
|
||||
# Create systemd service file
|
||||
cat > /etc/systemd/system/vigil.service << EOF
|
||||
echo "Creating systemd service..."
|
||||
cat > /etc/systemd/system/vigil.service << 'EOF'
|
||||
[Unit]
|
||||
Description=Vigil Monitoring Service
|
||||
Description=Vigil - APT Update Monitor
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=$ACTUAL_USER
|
||||
WorkingDirectory=/opt/vigil
|
||||
Environment="PATH=/opt/vigil/.venv/bin"
|
||||
ExecStart=/opt/vigil/.venv/bin/python3 /opt/vigil/main.py
|
||||
ExecStart=/opt/vigil/.venv/bin/python /opt/vigil/main.py serve --check-daily 18
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
@ -337,26 +158,53 @@ RestartSec=10
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
# Reload systemd, enable and start the service
|
||||
systemctl daemon-reload
|
||||
systemctl enable vigil.service
|
||||
systemctl start vigil.service
|
||||
echo "✓ Systemd service created (not enabled or started)"
|
||||
|
||||
echo "[OK] Vigil service has been created and started"
|
||||
echo "You can check its status with: systemctl status vigil"
|
||||
# Create a command to run vigil
|
||||
echo "Creating vigil command..."
|
||||
cat > /usr/local/bin/vigil << 'EOF'
|
||||
#!/bin/bash
|
||||
exec /opt/vigil/.venv/bin/python /opt/vigil/main.py "$@"
|
||||
EOF
|
||||
|
||||
chmod +x /usr/local/bin/vigil
|
||||
echo "✓ Command 'vigil' available system-wide"
|
||||
|
||||
echo ""
|
||||
echo "✓ Vigil installed successfully!"
|
||||
echo ""
|
||||
|
||||
# Check what needs to be configured
|
||||
NEEDS_CONFIG=false
|
||||
|
||||
if [[ ! -f /etc/vigil/.env ]]; then
|
||||
echo "⚠️ Missing: /etc/vigil/.env"
|
||||
echo " Create this file with your SMTP credentials"
|
||||
echo " See README for template: /opt/vigil/README.md"
|
||||
echo ""
|
||||
NEEDS_CONFIG=true
|
||||
fi
|
||||
|
||||
if [[ ! -f /etc/vigil/users.json ]]; then
|
||||
echo "⚠️ Missing: /etc/vigil/users.json"
|
||||
echo " Create this file with recipient email addresses"
|
||||
echo " Example: [\"admin@example.com\"]"
|
||||
echo ""
|
||||
NEEDS_CONFIG=true
|
||||
fi
|
||||
|
||||
if [[ "$NEEDS_CONFIG" == "true" ]]; then
|
||||
echo "Next steps:"
|
||||
echo " 1. Configure the files above"
|
||||
echo " 2. Test: sudo vigil now"
|
||||
echo " 3. Enable service: sudo systemctl enable --now vigil"
|
||||
else
|
||||
echo "Skipping autostart configuration"
|
||||
echo "✓ Configuration files found"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Test: sudo vigil now"
|
||||
echo " 2. Enable service: sudo systemctl enable --now vigil"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo "Vigil has been installed successfully!"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
echo "To use vigil, run: source ~/.bashrc && vigil"
|
||||
echo "Or simply open a new terminal and run: vigil"
|
||||
echo ""
|
||||
if [[ "${answer,,}" == "y" ]]; then
|
||||
echo "Vigil is now running as a system service."
|
||||
echo "Use 'systemctl status vigil' to check its status"
|
||||
fi
|
||||
152
main.py
152
main.py
@ -11,27 +11,58 @@ from typing import Union
|
||||
|
||||
import services.apt
|
||||
import services.mail
|
||||
import html as hypertext
|
||||
import re
|
||||
|
||||
from socket import gethostname
|
||||
|
||||
import json
|
||||
from os.path import dirname, join, exists
|
||||
from os.path import exists
|
||||
|
||||
from services.logger import logger
|
||||
|
||||
import typer
|
||||
|
||||
import signal
|
||||
|
||||
# Its beautiful ;)
|
||||
EMAIL_REGEX = re.compile(r"""
|
||||
(?:[a-z0-9!#$%&'*+\x2f=?^_`\x7b-\x7d~\x2d]+(?:\.[a-z0-9!#$%&'*+\x2f=?^_`\x7b-\x7d~\x2d]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9\x2d]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9\x2d]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9\x2d]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
|
||||
""", re.VERBOSE | re.IGNORECASE)
|
||||
|
||||
# Change for version of Vigil
|
||||
__version__ = "1.0.0"
|
||||
|
||||
shutdown_flag = False
|
||||
|
||||
def handle_shutdown(signum, frame):
|
||||
global shutdown_flag
|
||||
logger.info("Shutdown signal received; finishing current cycle and exiting...")
|
||||
shutdown_flag = True
|
||||
|
||||
signal.signal(signal.SIGINT, handle_shutdown)
|
||||
signal.signal(signal.SIGTERM, handle_shutdown)
|
||||
|
||||
app = typer.Typer()
|
||||
|
||||
def wait_until(target_time):
|
||||
def wait_until_interruptible(target_time):
|
||||
global shutdown_flag
|
||||
while not shutdown_flag:
|
||||
now = datetime.now()
|
||||
seconds_to_wait = (target_time - now).total_seconds()
|
||||
if seconds_to_wait > 0:
|
||||
time.sleep(seconds_to_wait)
|
||||
remaining = (target_time - now).total_seconds()
|
||||
if remaining <= 0:
|
||||
return
|
||||
# sleep in small chunks so shutdown is responsive
|
||||
time.sleep(min(remaining, 0.5))
|
||||
|
||||
def schedule(mode, hour, minute=0, receiver_email=None):
|
||||
print(f"Scheduler started at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - Mode: {mode}")
|
||||
while True:
|
||||
global shutdown_flag
|
||||
logger.info(f"Scheduler started at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - Mode: {mode}")
|
||||
|
||||
while not shutdown_flag:
|
||||
try:
|
||||
now = datetime.now()
|
||||
|
||||
if mode == "daily":
|
||||
target = now.replace(hour=hour, minute=minute, second=0, microsecond=0)
|
||||
if target <= now:
|
||||
@ -43,11 +74,19 @@ def schedule(mode, hour, minute=0, receiver_email=None):
|
||||
else:
|
||||
raise ValueError("Mode must be 'daily' or 'hourly'.")
|
||||
|
||||
wait_until(target)
|
||||
logger.info(f"Next check scheduled for {target.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
wait_until_interruptible(target)
|
||||
if shutdown_flag:
|
||||
break
|
||||
|
||||
generate_email(receiver_email)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error in scheduled task: {e}")
|
||||
time.sleep(60) # Wait before retrying
|
||||
logger.error(f"Error in scheduled task: {e}", exc_info=True)
|
||||
time.sleep(60)
|
||||
|
||||
logger.info("Scheduler exited cleanly.")
|
||||
|
||||
|
||||
@app.command()
|
||||
def serve(receiver_email: str = None, check_hourly: bool = False, check_daily: str = "18"):
|
||||
@ -58,7 +97,7 @@ def serve(receiver_email: str = None, check_hourly: bool = False, check_daily: s
|
||||
- check_daily=int → hour of day for daily email
|
||||
"""
|
||||
|
||||
if check_hourly and check_daily:
|
||||
if check_hourly and check_daily not in [False, "false", "False", None]:
|
||||
check_daily = False
|
||||
|
||||
if check_hourly:
|
||||
@ -71,11 +110,11 @@ def serve(receiver_email: str = None, check_hourly: bool = False, check_daily: s
|
||||
try:
|
||||
hour = int(check_daily)
|
||||
except ValueError:
|
||||
print(f"Invalid check_daily value: {check_daily}")
|
||||
exit(1)
|
||||
logger.error(f"Invalid check_daily value: {check_daily}")
|
||||
raise typer.Exit(1)
|
||||
schedule("daily", hour, receiver_email=receiver_email)
|
||||
else:
|
||||
print("No schedule selected.")
|
||||
logger.error("No schedule selected.")
|
||||
|
||||
@app.command()
|
||||
def now(receiver_email: str = None):
|
||||
@ -87,25 +126,13 @@ def now(receiver_email: str = None):
|
||||
def generate_email(receiver_emails: Union[list, None]):
|
||||
services.apt.require_root()
|
||||
if not services.apt.detect_apt():
|
||||
print("Apt not found on this system.")
|
||||
exit(1)
|
||||
logger.error("Apt not found on this system.")
|
||||
raise typer.Exit(1)
|
||||
try:
|
||||
updates = services.apt.check_updates()
|
||||
|
||||
# For testing
|
||||
#updates = {
|
||||
# "vim": {
|
||||
# "installed_version": "8.2.3400",
|
||||
# "latest_version": "8.2.3400",
|
||||
# "repo": "universe",
|
||||
# "security": True
|
||||
# },
|
||||
# "vim-gtk3": {
|
||||
# "installed_version": "8.2.3400",
|
||||
# "latest_version": "8.2.3400",
|
||||
# "repo": "universe",
|
||||
# "security": False
|
||||
# }
|
||||
#}
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to check for updates: {e}", exc_info=True)
|
||||
raise typer.Exit(1)
|
||||
|
||||
receiver_email = []
|
||||
if receiver_emails:
|
||||
@ -116,13 +143,27 @@ def generate_email(receiver_emails: Union[list, None]):
|
||||
|
||||
# If no CLI emails are provided
|
||||
if not receiver_email:
|
||||
users_json_path = join(dirname(__file__), "users.json")
|
||||
users_json_path = "/etc/vigil/users.json"
|
||||
if exists(users_json_path):
|
||||
try:
|
||||
with open(users_json_path, "r") as f:
|
||||
receiver_email = json.load(f)
|
||||
data = json.load(f)
|
||||
if not isinstance(data, list):
|
||||
logger.error("users.json must contain a list of email addresses")
|
||||
raise typer.Exit(1)
|
||||
receiver_email = [str(email).strip() for email in data]
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f"Invalid JSON in users.json: {e}")
|
||||
raise typer.Exit(1)
|
||||
else:
|
||||
print("No email address provided and users.json not found.")
|
||||
exit(1)
|
||||
logger.error("No email address provided and /etc/vigil/users.json not found.")
|
||||
raise typer.Exit(1)
|
||||
|
||||
# Validate email address(es)
|
||||
for email in receiver_email:
|
||||
if not EMAIL_REGEX.match(email):
|
||||
logger.error(f"Invalid email address: {email}")
|
||||
raise typer.Exit(1)
|
||||
|
||||
# Get how many security updates are available
|
||||
security_updates = 0
|
||||
@ -137,7 +178,7 @@ def generate_email(receiver_emails: Union[list, None]):
|
||||
|
||||
# Check if there are any updates at all
|
||||
if total_updates == 0:
|
||||
print("No updates available.")
|
||||
logger.info("No updates available.")
|
||||
return
|
||||
|
||||
# Get system hostname
|
||||
@ -154,10 +195,10 @@ def generate_email(receiver_emails: Union[list, None]):
|
||||
continue
|
||||
chunk = f'''
|
||||
<tr>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{package}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{updates[package]["installed_version"]}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{updates[package]["latest_version"]}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{updates[package]["repo"]}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{hypertext.escape(package)}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{hypertext.escape(updates[package]["installed_version"])}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{hypertext.escape(updates[package]["latest_version"])}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{hypertext.escape(updates[package]["repo"])}</td>
|
||||
</tr>
|
||||
'''
|
||||
security_chunks += chunk
|
||||
@ -185,10 +226,10 @@ def generate_email(receiver_emails: Union[list, None]):
|
||||
continue
|
||||
chunk = f'''
|
||||
<tr>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{package}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{updates[package]["installed_version"]}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{updates[package]["latest_version"]}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{updates[package]["repo"]}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{hypertext.escape(package)}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{hypertext.escape(updates[package]["installed_version"])}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{hypertext.escape(updates[package]["latest_version"])}</td>
|
||||
<td style="border: 1px solid #ddd; padding: 8px;">{hypertext.escape(updates[package]["repo"])}</td>
|
||||
</tr>
|
||||
'''
|
||||
general_chunks += chunk
|
||||
@ -210,10 +251,29 @@ def generate_email(receiver_emails: Union[list, None]):
|
||||
|
||||
html = security + general
|
||||
|
||||
try:
|
||||
services.mail.send_email(receiver_email, subject, html)
|
||||
logger.info(f"Update notification sent: {security_updates} security, {general_updates} general updates to {len(receiver_email)} recipient(s)")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to send email notification: {e}", exc_info=True)
|
||||
raise typer.Exit(1)
|
||||
|
||||
def version_callback(value: bool):
|
||||
if value:
|
||||
typer.echo(f"Vigil {__version__}")
|
||||
raise typer.Exit()
|
||||
|
||||
@app.callback()
|
||||
def callback():
|
||||
def callback(
|
||||
version: bool = typer.Option(
|
||||
None,
|
||||
"--version",
|
||||
"-v",
|
||||
callback=version_callback,
|
||||
is_eager=True,
|
||||
help="Show version and exit"
|
||||
)
|
||||
):
|
||||
"""
|
||||
Checks apt for upgrades and emails them
|
||||
"""
|
||||
|
||||
@ -3,8 +3,8 @@ dotenv==0.9.9
|
||||
markdown-it-py==4.0.0
|
||||
mdurl==0.1.2
|
||||
Pygments==2.19.2
|
||||
python-dotenv==1.1.1
|
||||
python-dotenv==1.2.1
|
||||
rich==14.2.0
|
||||
shellingham==1.5.4
|
||||
typer==0.19.2
|
||||
typer==0.20.0
|
||||
typing_extensions==4.15.0
|
||||
|
||||
0
services/__init__.py
Normal file
0
services/__init__.py
Normal file
@ -6,13 +6,15 @@
|
||||
# © Uthmn 2025 under MIT license
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
from os import geteuid
|
||||
import sys
|
||||
import re
|
||||
|
||||
from services.logger import logger
|
||||
|
||||
def require_root():
|
||||
if os.geteuid() != 0:
|
||||
print("This script requires root privileges. Please run with sudo.")
|
||||
if geteuid() != 0:
|
||||
logger.error("This script requires root privileges. Please run with sudo.")
|
||||
sys.exit(1)
|
||||
|
||||
def detect_apt():
|
||||
@ -74,4 +76,4 @@ if __name__ == "__main__":
|
||||
require_root()
|
||||
if detect_apt():
|
||||
updates = check_updates()
|
||||
print(updates)
|
||||
logger.info(updates)
|
||||
|
||||
46
services/logger.py
Normal file
46
services/logger.py
Normal file
@ -0,0 +1,46 @@
|
||||
# _ __________________
|
||||
# | | / / _/ ____/ _/ /
|
||||
# | | / // // / __ / // /
|
||||
# | |/ // // /_/ // // /___
|
||||
# |___/___/\____/___/_____/
|
||||
# © Uthmn 2025 under MIT license
|
||||
|
||||
import logging
|
||||
from logging.handlers import RotatingFileHandler
|
||||
from os import makedirs
|
||||
from os.path import exists
|
||||
|
||||
# Setup logging once, globally
|
||||
logger = logging.getLogger('vigil')
|
||||
|
||||
# Prevent duplicate setup
|
||||
if not logger.handlers:
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# Create log directory if it doesn't exist
|
||||
log_dir = '/var/log/vigil'
|
||||
if not exists(log_dir):
|
||||
makedirs(log_dir, exist_ok=True)
|
||||
|
||||
# File handler with rotation
|
||||
file_handler = RotatingFileHandler(
|
||||
'/var/log/vigil/vigil.log',
|
||||
maxBytes=10*1024*1024, # 10MB
|
||||
backupCount=3
|
||||
)
|
||||
file_handler.setLevel(logging.INFO)
|
||||
file_handler.setFormatter(logging.Formatter(
|
||||
'%(asctime)s [%(levelname)s] %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
))
|
||||
|
||||
# Console handler (for systemd journal)
|
||||
console_handler = logging.StreamHandler()
|
||||
console_handler.setLevel(logging.INFO)
|
||||
console_handler.setFormatter(logging.Formatter(
|
||||
'%(asctime)s [%(levelname)s] %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
))
|
||||
|
||||
logger.addHandler(file_handler)
|
||||
logger.addHandler(console_handler)
|
||||
@ -13,16 +13,18 @@ from email import message_from_bytes
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from os import getenv
|
||||
from os.path import dirname, join, exists
|
||||
from os.path import exists
|
||||
import time
|
||||
|
||||
from services.logger import logger
|
||||
|
||||
# Exit if .env does not exist
|
||||
if not exists(join(dirname(__file__), "../.env")):
|
||||
print("Please create a .env file in the root directory.")
|
||||
if not exists("/etc/vigil/.env"):
|
||||
logger.error("Please create a .env file in /etc/vigil.")
|
||||
exit(1)
|
||||
|
||||
# Load environment variables from .env file
|
||||
dotenv_path = join(dirname(__file__), "../.env")
|
||||
dotenv_path = "/etc/vigil/.env"
|
||||
load_dotenv(dotenv_path)
|
||||
|
||||
# SMTP server settings
|
||||
@ -43,7 +45,7 @@ RETRY_DELAY = 2 # in seconds
|
||||
|
||||
# Check if all environment variables are set
|
||||
if not SMTP_SERVER or not SMTP_PORT or not SMTP_USERNAME or not SMTP_PASSWORD or not IMAP_SERVER or not IMAP_PORT or not IMAP_USERNAME or not IMAP_PASSWORD:
|
||||
print("Please set all environment variables in .env file.")
|
||||
logger.error("Please set all environment variables in .env file.")
|
||||
exit(1)
|
||||
|
||||
# Make sure SMTP and IMAP ports are integers
|
||||
@ -60,11 +62,11 @@ def connect_smtp_with_retry():
|
||||
except Exception as e:
|
||||
if attempt < MAX_RETRIES - 1:
|
||||
wait_time = RETRY_DELAY * (2 ** attempt) # Exponential backoff
|
||||
print(f"SMTP connection attempt {attempt + 1} failed: {e}")
|
||||
print(f"Retrying in {wait_time} seconds...")
|
||||
logger.error(f"SMTP connection attempt {attempt + 1} failed: {e}")
|
||||
logger.info(f"Retrying in {wait_time} seconds...")
|
||||
time.sleep(wait_time)
|
||||
else:
|
||||
print(f"Failed to connect to SMTP after {MAX_RETRIES} attempts: {e}")
|
||||
logger.error(f"Failed to connect to SMTP after {MAX_RETRIES} attempts: {e}")
|
||||
raise
|
||||
|
||||
def connect_imap_with_retry():
|
||||
@ -77,11 +79,11 @@ def connect_imap_with_retry():
|
||||
except Exception as e:
|
||||
if attempt < MAX_RETRIES - 1:
|
||||
wait_time = RETRY_DELAY * (2 ** attempt) # Exponential backoff
|
||||
print(f"IMAP connection attempt {attempt + 1} failed: {e}")
|
||||
print(f"Retrying in {wait_time} seconds...")
|
||||
logger.error(f"IMAP connection attempt {attempt + 1} failed: {e}")
|
||||
logger.info(f"Retrying in {wait_time} seconds...")
|
||||
time.sleep(wait_time)
|
||||
else:
|
||||
print(f"Failed to connect to IMAP after {MAX_RETRIES} attempts: {e}")
|
||||
logger.error(f"Failed to connect to IMAP after {MAX_RETRIES} attempts: {e}")
|
||||
raise
|
||||
|
||||
# Test all connections
|
||||
@ -89,14 +91,14 @@ try:
|
||||
server = connect_smtp_with_retry()
|
||||
server.quit()
|
||||
except Exception as e:
|
||||
print(f"Initial SMTP connection test failed: {e}")
|
||||
logger.error(f"Initial SMTP connection test failed: {e}")
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
M = connect_imap_with_retry()
|
||||
M.logout()
|
||||
except Exception as e:
|
||||
print(f"Initial IMAP connection test failed: {e}")
|
||||
logger.error(f"Initial IMAP connection test failed: {e}")
|
||||
exit(1)
|
||||
|
||||
def send_email(receiver_emails, subject, body):
|
||||
@ -113,11 +115,12 @@ def send_email(receiver_emails, subject, body):
|
||||
server = connect_smtp_with_retry()
|
||||
try:
|
||||
server.sendmail(sender_email, receiver_emails, message.as_string())
|
||||
print("HTML email sent successfully!")
|
||||
logger.info("HTML email sent successfully!")
|
||||
finally:
|
||||
server.quit()
|
||||
except Exception as e:
|
||||
print(f"Failed to send email: {e}")
|
||||
logger.error(f"Failed to send email: {e}")
|
||||
raise
|
||||
|
||||
def receive_emails(folder="INBOX", limit=50):
|
||||
emails = {}
|
||||
@ -131,7 +134,7 @@ def receive_emails(folder="INBOX", limit=50):
|
||||
# Get all message IDs
|
||||
typ, data = M.search(None, 'ALL')
|
||||
if typ != 'OK' or not data[0]:
|
||||
print("No messages found.")
|
||||
logger.info("No messages found.")
|
||||
return emails
|
||||
|
||||
all_ids = data[0].split()
|
||||
@ -140,7 +143,7 @@ def receive_emails(folder="INBOX", limit=50):
|
||||
for num in last_ids:
|
||||
typ, msg_data = M.fetch(num, '(RFC822)')
|
||||
if typ != 'OK':
|
||||
print(f"Failed to fetch message {num}")
|
||||
logger.error(f"Failed to fetch message {num}")
|
||||
continue
|
||||
|
||||
# Parse the email
|
||||
@ -185,6 +188,6 @@ def receive_emails(folder="INBOX", limit=50):
|
||||
M.logout()
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error receiving emails: {e}")
|
||||
logger.error(f"Error receiving emails: {e}")
|
||||
|
||||
return emails
|
||||
|
||||
108
uninstall.sh
108
uninstall.sh
@ -1,76 +1,70 @@
|
||||
#!/bin/bash
|
||||
|
||||
# TODO: Add uninstall to readme
|
||||
|
||||
# Just double check, check /opt/vigil exists, then remove it, also check+remove systemd service, remove aliases from bashrc and also dont offer but notify that dependencies not uninstalled
|
||||
|
||||
# Check if vigil is installed, if not then exit
|
||||
if [[ ! -d "/opt/vigil" ]]; then
|
||||
echo "Vigil is not installed. Exiting." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if we are running as root
|
||||
# Check if running as root
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "This script must be run as root" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the actual user (not root) for later use
|
||||
ACTUAL_USER=${SUDO_USER:-$USER}
|
||||
USER_HOME=$(eval echo ~$ACTUAL_USER)
|
||||
|
||||
# Now check if we are running on a supported system
|
||||
if [[ "$OSTYPE" != "linux-gnu"* ]]; then
|
||||
echo "This script is only supported on Linux" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Warning and countdown
|
||||
echo "WARNING: This will remove /opt/vigil and any related data."
|
||||
echo "Press Ctrl+C to cancel..."
|
||||
echo ""
|
||||
|
||||
for i in 5 4 3 2 1; do
|
||||
echo -n "$i..."
|
||||
sleep 1
|
||||
done
|
||||
echo "This will uninstall Vigil from your system."
|
||||
echo ""
|
||||
echo "What would you like to remove?"
|
||||
echo " 1) Everything (code, config, and logs)"
|
||||
echo " 2) Just the code (preserve /etc/vigil and /var/log/vigil)"
|
||||
echo " 3) Cancel"
|
||||
echo ""
|
||||
read -p "Enter choice [1-3]: " choice
|
||||
|
||||
# Final confirmation
|
||||
echo "Continue with uninstallation? (y/n)"
|
||||
read -r answer
|
||||
if [[ "${answer,,}" != "y" ]]; then
|
||||
echo "Uninstallation cancelled."
|
||||
case $choice in
|
||||
1)
|
||||
REMOVE_ALL=true
|
||||
;;
|
||||
2)
|
||||
REMOVE_ALL=false
|
||||
;;
|
||||
3)
|
||||
echo "Uninstall cancelled."
|
||||
exit 0
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Invalid choice. Uninstall cancelled."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Now delete the vigil directory
|
||||
# Stop and disable service
|
||||
echo ""
|
||||
echo "Removing Vigil installation..."
|
||||
echo "Stopping vigil service..."
|
||||
systemctl stop vigil 2>/dev/null
|
||||
systemctl disable vigil 2>/dev/null
|
||||
|
||||
# Remove systemd service
|
||||
echo "Removing systemd service..."
|
||||
rm -f /etc/systemd/system/vigil.service
|
||||
systemctl daemon-reload
|
||||
|
||||
# Remove command
|
||||
echo "Removing vigil command..."
|
||||
rm -f /usr/local/bin/vigil
|
||||
|
||||
# Remove code
|
||||
echo "Removing code from /opt/vigil..."
|
||||
rm -rf /opt/vigil
|
||||
|
||||
# Now delete the systemd service (if it exists)
|
||||
if [[ -f /etc/systemd/system/vigil.service ]]; then
|
||||
echo "Removing Vigil systemd service..."
|
||||
systemctl stop vigil.service 2>/dev/null
|
||||
systemctl disable vigil.service 2>/dev/null
|
||||
rm /etc/systemd/system/vigil.service
|
||||
systemctl daemon-reload
|
||||
if [[ "$REMOVE_ALL" == "true" ]]; then
|
||||
echo "Removing configuration from /etc/vigil..."
|
||||
rm -rf /etc/vigil
|
||||
echo "Removing logs from /var/log/vigil..."
|
||||
rm -rf /var/log/vigil
|
||||
echo ""
|
||||
echo "✓ Vigil completely removed from your system"
|
||||
else
|
||||
echo "No systemd service found (skipping)"
|
||||
fi
|
||||
|
||||
# Now delete the aliases from bashrc
|
||||
echo "Removing Vigil aliases from bashrc..."
|
||||
if grep -q "alias vigil=" "$USER_HOME/.bashrc" 2>/dev/null; then
|
||||
sed -i '/alias vigil=/d' "$USER_HOME/.bashrc"
|
||||
echo "Aliases removed from $USER_HOME/.bashrc"
|
||||
else
|
||||
echo "No aliases found in bashrc"
|
||||
echo ""
|
||||
echo "✓ Vigil code removed"
|
||||
echo "✓ Configuration preserved in /etc/vigil"
|
||||
echo "✓ Logs preserved in /var/log/vigil"
|
||||
echo ""
|
||||
echo "To reinstall: curl ... | sudo bash"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Dependencies not uninstalled. Please uninstall them manually if needed: python3, git, pip"
|
||||
echo "Vigil has been uninstalled successfully."
|
||||
|
||||
Loading…
Reference in New Issue
Block a user