Files
spoolman2/scripts/install.sh
foxt 208e2f67e3 Install script: Don't bother using sudo if user is running as root
On some systems, sudo isn't present by default, so allow the user to manually elevate the script bypassing the use of sudo.
2024-08-09 10:01:59 +01:00

284 lines
9.8 KiB
Bash
Executable File

#!/bin/bash
# ANSI color codes
GREEN='\033[0;32m'
ORANGE='\033[0;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Warn with a prompt if we're running as root
SUDO=sudo
if [ "$EUID" -eq 0 ]; then
echo -e "${ORANGE}WARNING: You are running this script as root. It is recommended to run this script as a non-root user.${NC}"
echo -e "${ORANGE}Do you want to continue? (y/n)${NC}"
read choice
if [ "$choice" != "y" ] && [ "$choice" != "Y" ]; then
echo -e "${ORANGE}Aborting installation.${NC}"
exit 1
fi
SUDO=
fi
# CD to project root if we're in the scripts dir
current_dir=$(pwd)
if [ "$(basename "$current_dir")" = "scripts" ]; then
cd ..
fi
#
# Python version verification
#
if ! command -v python3 &>/dev/null; then
echo -e "${ORANGE}Python 3 is not installed or not found. Please install at least Python 3.9 before you continue.${NC}"
exit 1
fi
python_version=$(python3 --version) || exit 1
version_number=$(echo "$python_version" | awk '{print $2}')
IFS='.' read -r major minor patch <<< "$version_number"
if [[ "$major" -eq 3 && "$minor" -ge 9 ]]; then
echo -e "${GREEN}Python 3.9 or later is installed (Current version: $version_number)${NC}"
else
if [[ -f /etc/os-release ]]; then
source /etc/os-release
if [[ "$VERSION_CODENAME" == "buster" ]]; then
echo -e "${ORANGE}Python 3.9 or later is not installed (Current version: $version_number)${NC}"
echo -e "${ORANGE}You are running an outdated version of Debian/Raspbian (Buster). If you upgrade to Bullseye, you will get the correct python version. Please see guides online on how to upgrade your operating system.${NC}"
exit 1
fi
fi
echo -e "${ORANGE}Current version of Python ($version_number) is too old for Spoolman.${NC}"
echo -e "${ORANGE}Please look up how to install Python 3.9 or later for your specific operating system.${NC}"
exit 1
fi
#
# Get os package manager
#
if [[ -f /etc/os-release ]]; then
source /etc/os-release
if [[ "$ID_LIKE" == *"debian"* || "$ID" == *"debian"* ]]; then
pkg_manager="apt-get"
update_cmd="$SUDO $pkg_manager update"
install_cmd="$SUDO $pkg_manager install -y"
echo -e "${GREEN}Detected Debian-based system. Using apt-get package manager.${NC}"
elif [[ "$ID_LIKE" == *"arch"* || "$ID" == *"arch"* ]]; then
pkg_manager="pacman"
update_cmd="$SUDO $pkg_manager -Sy"
install_cmd="$SUDO $pkg_manager -S --noconfirm"
echo -e "${GREEN}Detected Arch-based system. Using pacman package manager.${NC}"
else
echo -e "${ORANGE}Your operating system is not supported. Either try to install manually or reach out to spoolman github for support.${NC}"
exit 1
fi
fi
# Run pkg manager update
echo -e "${GREEN}Updating $pkg_manager cache...${NC}"
$update_cmd || exit 1
packages=""
if ! python3 -c 'import venv, ensurepip' &>/dev/null; then
echo -e "${ORANGE}Python venv module is not accessible. Installing venv...${NC}"
if [[ "$pkg_manager" == "apt-get" ]]; then
packages+=" python3-venv"
elif [[ "$pkg_manager" == "pacman" ]]; then
packages+=" python-virtualenv"
fi
fi
if ! command -v pip3 &>/dev/null; then
echo -e "${ORANGE}Python pip is not installed. Installing pip...${NC}"
if [[ "$pkg_manager" == "apt-get" ]]; then
packages+=" python3-pip"
elif [[ "$pkg_manager" == "pacman" ]]; then
packages+=" python-pip"
fi
fi
if ! command -v pg_config &>/dev/null; then
echo -e "${ORANGE}pg_config is not available. Installing libpq-dev...${NC}"
if [[ "$pkg_manager" == "apt-get" ]]; then
packages+=" libpq-dev"
elif [[ "$pkg_manager" == "pacman" ]]; then
packages+=" postgresql-libs"
fi
fi
if ! command -v unzip &>/dev/null; then
echo -e "${ORANGE}unzip is not available. Installing unzip...${NC}"
packages+=" unzip"
fi
if [[ -n "$packages" ]]; then
$install_cmd $packages || exit 1
fi
#
# Update pip
#
echo -e "${GREEN}Updating pip...${NC}"
# Run pip upgrade command and capture stdout
upgrade_output=$(python3 -m pip install --user --upgrade pip 2>&1)
exit_code=$?
# Check if the upgrade command failed and contains the specified error message
is_externally_managed_env=$(echo "$upgrade_output" | grep "error: externally-managed-environment")
if [[ $exit_code -ne 0 ]]; then
if [[ $is_externally_managed_env ]]; then
echo -e "${GREEN}Warning:${NC} Failed to upgrade pip since it's version is managed by the OS. Continuing anyway..."
else
echo -e "${GREEN}Error:${NC} Pip upgrade failed with exit code $exit_code and the following output:"
echo "$upgrade_output"
exit 1
fi
else
echo -e "${GREEN}Pip updated successfully.${NC}"
fi
#
# Install various pip packages if needed
#
echo -e "${GREEN}Installing system-wide pip packages needed for Spoolman...${NC}"
if [[ $is_externally_managed_env ]]; then
echo -e "${GREEN}Installing the packages using apt-get instead of pip since pip is externally managed...${NC}"
if [[ "$pkg_manager" == "apt-get" ]]; then
packages="python3-setuptools python3-wheel"
elif [[ "$pkg_manager" == "pacman" ]]; then
packages="python-setuptools python-wheel"
fi
$install_cmd $packages || exit 1
else
packages="setuptools wheel"
for package in $packages; do
if ! pip3 show "$package" &>/dev/null; then
echo -e "${GREEN}Installing $package...${NC}"
pip3 install --user "$package" || exit 1
fi
done
fi
#
# Add python bin dir to PATH if needed
#
user_python_bin_dir=$(python3 -m site --user-base)/bin
if [[ ! "$PATH" =~ "$user_python_bin_dir" ]]; then
export PATH=$user_python_bin_dir:$PATH
fi
#
# Install Spoolman
#
# Install dependencies
echo -e "${GREEN}Installing Spoolman backend and its dependencies...${NC}"
# Create venv if it doesn't exist
if [ ! -d ".venv" ]; then
python3 -m venv .venv || exit 1
fi
# Activate venv
source .venv/bin/activate || exit 1
# Install dependencies using pip
pip3 install -r requirements.txt || exit 1
#
# Initialize the .env file if it doesn't exist
#
if [ ! -f ".env" ]; then
echo -e "${ORANGE}.env file not found. Creating it...${NC}"
cp .env.example .env
fi
#
# Add execute permissions of all files in scripts dir
#
echo -e "${GREEN}Adding execute permissions to all files in scripts dir...${NC}"
chmod +x scripts/*.sh
#
# Install systemd service
#
echo -e "${CYAN}Do you want to install Spoolman as a systemd service? This will automatically start Spoolman when your server starts. (y/n)${NC}"
read choice
if [ "$choice" == "y" ] || [ "$choice" == "Y" ]; then
systemd_user_dir="$HOME/.config/systemd/user"
service_name="Spoolman"
# Check if user-level systemd service exists and remove it
if [ -f "$systemd_user_dir/$service_name.service" ]; then
echo -e "${ORANGE}User-level systemd service already installed. Removing the existing service.${NC}"
systemctl --user stop Spoolman # Stop the service if it's running
systemctl --user disable Spoolman # Disable the service
rm "$systemd_user_dir/$service_name.service" # Remove the user-level service unit file
systemctl --user daemon-reload # Reload the systemd user service manager
fi
# Get the parent directory of the installer script
script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
spoolman_dir=$(dirname "$script_dir")
# Verify that we found the right spoolman dir by checking for the existence of pyproject.toml
if [ ! -f "$spoolman_dir/pyproject.toml" ]; then
echo -e "${ORANGE}Could not automatically find the Spoolman directory. Please specify the path to the Spoolman directory (the directory containing pyproject.toml):${NC}"
read spoolman_dir
# Expand the path
spoolman_dir=$(eval echo "$spoolman_dir")
# Verify again
if [ ! -f "$spoolman_dir/pyproject.toml" ]; then
echo -e "${ORANGE}Could not find pyproject.toml in $spoolman_dir. Aborting installation.${NC}"
exit 1
fi
fi
# Define the systemd service unit file
service_unit="[Unit]
Description=Spoolman
[Service]
Type=simple
ExecStart=bash $spoolman_dir/scripts/start.sh
WorkingDirectory=$spoolman_dir
User=$USER
Restart=always
[Install]
WantedBy=default.target
"
# Create the systemd service unit file
service_file="/etc/systemd/system/$service_name.service"
echo "$service_unit" | $SUDO tee "$service_file" > /dev/null
# Reload the systemd user service manager
$SUDO systemctl daemon-reload
# Enable and start the service
$SUDO systemctl enable "$service_name"
$SUDO systemctl start "$service_name"
# Load .env file now
set -o allexport
source .env
set +o allexport
local_ip=$(hostname -I | awk '{print $1}')
echo -e "${GREEN}Spoolman systemd service has been installed and Spoolman is now starting.${NC}"
echo -e "${GREEN}Spoolman will soon be reachable at ${ORANGE}http://$local_ip:$SPOOLMAN_PORT${NC}"
echo -e "${GREEN}Please note that the displayed IP address may be incorrect for your setup. If needed, replace it manually with the correct IP.${NC}"
echo -e "${GREEN}You can start/restart/stop the service by running e.g. '${CYAN}sudo systemctl stop Spoolman${GREEN}'${NC}"
echo -e "${GREEN}You can disable the service from starting automatically by running '${CYAN}sudo systemctl disable Spoolman${GREEN}'${NC}"
echo -e "${GREEN}You can view the Spoolman logs by running '${CYAN}sudo journalctl -u Spoolman${GREEN}'${NC}"
else
echo -e "${ORANGE}Skipping systemd service installation.${NC}"
echo -e "${ORANGE}You can start Spoolman manually by running 'bash scripts/start.sh'${NC}"
fi
echo -e "${GREEN}Spoolman has been installed successfully!${NC}"
echo -e "${GREEN}If you want to connect to an external database, you can edit the .env file and restart the service.${NC}"