View Raw #!/bin/bash
# 5q12's Indexer Installation Script
# Installer version: 2.0.0
set -e
SCRIPT_NAME="5q12-index"
CONFIG_DIR="/etc/5q12-indexer"
CONFIG_FILE="$CONFIG_DIR/indexer.conf"
BACKUP_DIR="$CONFIG_DIR/backups"
SYMLINK_PATH="/usr/local/bin/$SCRIPT_NAME"
NGINX_CONFIG_PATH="/etc/nginx/sites-available/5q12-indexer.conf"
NGINX_ENABLED_PATH="/etc/nginx/sites-enabled/5q12-indexer.conf"
REPO_BASE_URL="https://ccls.icu/src/repositories/5q12-indexer/main"
REPO_LIST_URL="$REPO_BASE_URL/repo/"
VERSION_URL="https://ccls.icu/src/repositories/5q12-indexer/version.txt"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
check_root() {
if [[ $EUID -eq 0 ]]; then
return 0
else
return 1
fi
}
get_latest_version() {
curl -s "$VERSION_URL" 2>/dev/null | tr -d '\n\r' || echo "unknown"
}
get_installation_config() {
if [[ -f "$CONFIG_FILE" ]]; then
source "$CONFIG_FILE" 2>/dev/null || true
fi
}
get_current_version() {
get_installation_config
if [[ -n "$INDEXER_VERSION" ]]; then
echo "$INDEXER_VERSION"
else
echo "not installed"
fi
}
get_installation_path() {
get_installation_config
if [[ -n "$INDEXER_PATH" ]]; then
echo "$INDEXER_PATH"
else
echo ""
fi
}
save_installation_config() {
local version="$1"
local path="$2"
local install_date="$3"
sudo mkdir -p "$CONFIG_DIR"
sudo mkdir -p "$BACKUP_DIR"
cat << EOF | sudo tee "$CONFIG_FILE" > /dev/null
INDEXER_VERSION="$version"
INDEXER_PATH="$path"
INDEXER_INSTALL_DATE="$install_date"
INDEXER_NGINX_CONFIG="$NGINX_CONFIG_PATH"
INDEXER_SCRIPT_VERSION="2.0.0"
EOF
log_info "Installation config saved to $CONFIG_FILE"
}
check_requirements() {
local missing_requirements=()
local nginx_ok=false
local php_ok=false
log_info "Checking system requirements..."
if command -v nginx >/dev/null 2>&1; then
local nginx_version=$(nginx -v 2>&1 | grep -oP 'nginx/\K[0-9.]+')
local required_version="1.14"
if [[ $(printf '%s\n' "$required_version" "$nginx_version" | sort -V | head -n1) = "$required_version" ]]; then
log_success "Nginx $nginx_version found (>= $required_version required)"
nginx_ok=true
else
log_warning "Nginx $nginx_version found but version >= $required_version required"
missing_requirements+=("nginx-upgrade")
fi
else
log_warning "Nginx not found"
missing_requirements+=("nginx")
fi
if command -v php >/dev/null 2>&1; then
local php_version=$(php -v | grep -oP 'PHP \K[0-9.]+' | head -n1)
local required_php="8.3"
if [[ $(printf '%s\n' "$required_php" "$php_version" | sort -V | head -n1) = "$required_php" ]]; then
log_success "PHP $php_version found (>= $required_php required)"
php_ok=true
else
log_warning "PHP $php_version found but version >= $required_php required"
missing_requirements+=("php-upgrade")
fi
else
log_warning "PHP not found"
missing_requirements+=("php")
php_ok=false
fi
echo "${missing_requirements[@]}"
}
check_and_install_php_extensions() {
log_info "Checking PHP extensions..."
local required_extensions=("json" "fileinfo" "mbstring" "sqlite3" "zip" "curl" "openssl")
local missing_extensions=()
for ext in "${required_extensions[@]}"; do
if ! php -m | grep -q "^$ext$"; then
missing_extensions+=("$ext")
fi
done
if [[ ${#missing_extensions[@]} -eq 0 ]]; then
log_success "All required PHP extensions found"
return 0
fi
log_warning "Missing PHP extensions: ${missing_extensions[*]}"
log_info "Installing missing PHP extensions..."
sudo apt install -y php8.3-mbstring php8.3-sqlite3 php8.3-zip php8.3-curl
sudo systemctl restart php8.3-fpm || sudo systemctl restart php-fpm
log_info "Verifying PHP extensions..."
local still_missing=()
for ext in "${required_extensions[@]}"; do
if ! php -m | grep -q "^$ext$"; then
still_missing+=("$ext")
fi
done
if [[ ${#still_missing[@]} -eq 0 ]]; then
log_success "All PHP extensions now available"
else
log_warning "Some extensions still missing: ${still_missing[*]}"
log_info "These may be included under different names or already available"
fi
}
install_requirements() {
local requirements=("$@")
if [[ ${#requirements[@]} -eq 0 ]]; then
log_success "All requirements are already satisfied"
return 0
fi
log_warning "Missing requirements detected: ${requirements[*]}"
echo
read -p "Would you like to install the missing requirements? (y/n): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_error "Installation cannot continue without required dependencies"
exit 1
fi
log_info "Installing missing requirements..."
sudo apt update
log_info "Checking for conflicting web servers..."
if systemctl is-active --quiet apache2; then
log_warning "Apache2 is running, stopping and disabling it..."
sudo systemctl stop apache2
sudo systemctl disable apache2
fi
if systemctl is-active --quiet lighttpd; then
log_warning "Lighttpd is running, stopping and disabling it..."
sudo systemctl stop lighttpd
sudo systemctl disable lighttpd
fi
for req in "${requirements[@]}"; do
case $req in
"nginx"|"nginx-upgrade")
log_info "Installing/upgrading Nginx..."
sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx
;;
"php"|"php-upgrade")
log_info "Installing/upgrading PHP and PHP-FPM (without Apache2)..."
sudo apt install -y php-fpm php-cli
sudo systemctl enable php8.3-fpm || sudo systemctl enable php-fpm
sudo systemctl start php8.3-fpm || sudo systemctl start php-fpm
;;
esac
done
if dpkg -l | grep -q apache2; then
log_info "Removing Apache2 that was installed as dependency..."
sudo apt remove -y apache2 apache2-bin apache2-data apache2-utils libapache2-mod-php8.3 || true
sudo apt autoremove -y || true
fi
log_success "Requirements installation completed"
}
create_nginx_config() {
local web_path="$1"
log_info "Creating Nginx configuration..."
local temp_config=$(mktemp)
if ! curl -s -L -o "$temp_config" "$REPO_BASE_URL/5q12-indexer.conf/"; then
log_error "Failed to download nginx config template"
rm -f "$temp_config"
exit 1
fi
sed "s|{WEB_PATH}|$web_path|g" "$temp_config" | sudo tee "$NGINX_CONFIG_PATH" > /dev/null
rm -f "$temp_config"
sudo ln -sf "$NGINX_CONFIG_PATH" "$NGINX_ENABLED_PATH"
if ! sudo nginx -t; then
log_error "Nginx configuration test failed"
log_info "Config file content:"
sudo cat "$NGINX_CONFIG_PATH"
exit 1
fi
sudo systemctl reload nginx
log_success "Nginx configuration created and enabled"
log_info "Document root: $web_path"
log_info "Config file: $NGINX_CONFIG_PATH"
}
download_indexer_files() {
local install_path="$1"
local temp_file_list=$(mktemp)
log_info "Fetching file list from repository..."
if ! curl -s -L "$REPO_LIST_URL" > "$temp_file_list"; then
log_error "Failed to fetch file list from repository"
rm -f "$temp_file_list"
exit 1
fi
# Parse the file list and download each file
local total_files=0
local downloaded_files=0
local failed_downloads=()
# Count total files first
while IFS= read -r line; do
if [[ $line =~ \"([^\"]+)\".+\"([^\"]+)\" ]]; then
((total_files++))
fi
done < "$temp_file_list"
log_info "Found $total_files files to download"
# Reset file pointer and download files
while IFS= read -r line; do
if [[ $line =~ \"([^\"]+)\".+\"([^\"]+)\" ]]; then
local filename="${BASH_REMATCH[1]}"
local fileurl="${BASH_REMATCH[2]}"
# Determine the local file path based on the URL structure
local local_path=""
if [[ $fileurl =~ indexer_files/(.+)/ ]]; then
local_path=".indexer_files/${BASH_REMATCH[1]}"
elif [[ $filename == "index.php" || $filename == "5q12-indexer.conf" ]]; then
local_path="$filename"
else
local_path="$filename"
fi
local full_local_path="$install_path/$local_path"
local dir_path=$(dirname "$full_local_path")
# Create directory if it doesn't exist
if [[ ! -d "$dir_path" ]]; then
sudo mkdir -p "$dir_path"
fi
# Download the file
((downloaded_files++))
log_info "[$downloaded_files/$total_files] Downloading $filename..."
if sudo curl -s -L -o "$full_local_path" "$fileurl"; then
# Set proper permissions
if [[ $filename == "index.php" ]]; then
sudo chmod 644 "$full_local_path"
elif [[ $local_path == *.png || $local_path == *.css || $local_path == *.json || $local_path == *.woff2 || $local_path == *.ico ]]; then
sudo chmod 644 "$full_local_path"
else
sudo chmod 644 "$full_local_path"
fi
sudo chown www-data:www-data "$full_local_path"
else
log_warning "Failed to download $filename from $fileurl"
failed_downloads+=("$filename")
fi
fi
done < "$temp_file_list"
rm -f "$temp_file_list"
if [[ ${#failed_downloads[@]} -gt 0 ]]; then
log_warning "Failed to download ${#failed_downloads[@]} files: ${failed_downloads[*]}"
fi
log_success "Downloaded $((downloaded_files - ${#failed_downloads[@]}))/$total_files files successfully"
# Create files directory
local files_dir="$install_path/files"
if [[ ! -d "$files_dir" ]]; then
sudo mkdir -p "$files_dir"
sudo chown www-data:www-data "$files_dir"
sudo chmod 755 "$files_dir"
log_info "Created files directory: $files_dir"
fi
}
install_indexer() {
local install_path="$1"
if [[ -z "$install_path" ]]; then
log_error "Installation path is required"
exit 1
fi
if [[ ! "$install_path" = /* ]]; then
install_path="$(pwd)/$install_path"
fi
if [[ ! -d "$install_path" ]]; then
log_info "Creating directory: $install_path"
sudo mkdir -p "$install_path"
fi
sudo chown -R www-data:www-data "$install_path"
sudo chmod 755 "$install_path"
# Download all indexer files
download_indexer_files "$install_path"
log_success "Indexer files downloaded to $install_path"
# Test the installation
log_info "Testing indexer installation..."
if (cd "$install_path" && sudo -u www-data php -l index.php > /dev/null 2>&1); then
log_success "Indexer installation test passed"
else
log_warning "Indexer installation test failed, but installation may still work"
fi
local latest_version=$(get_latest_version)
local install_date=$(date '+%Y-%m-%d %H:%M:%S')
save_installation_config "$latest_version" "$install_path" "$install_date"
log_success "Installation completed!"
log_info "Indexer installed at: $install_path"
log_info "Version: $latest_version"
log_info "Nginx config: $NGINX_CONFIG_PATH"
log_info "Access URL: http://localhost:5012"
echo "$install_path"
}
backup_config_files() {
local install_path="$1"
local backup_name="config_backup_$(date +%Y%m%d_%H%M%S)"
local backup_path="$BACKUP_DIR/$backup_name"
sudo mkdir -p "$backup_path"
# Backup config.json if it exists
if [[ -f "$install_path/.indexer_files/config.json" ]]; then
sudo cp "$install_path/.indexer_files/config.json" "$backup_path/"
log_info "Backed up config.json to $backup_path/"
fi
echo "$backup_path"
}
update_indexer() {
log_info "Checking for updates..."
local current_version=$(get_current_version)
local latest_version=$(get_latest_version)
local install_path=$(get_installation_path)
if [[ "$current_version" == "not installed" ]]; then
log_error "No installation found. Use 'install' command first."
exit 1
fi
if [[ -z "$install_path" ]]; then
log_error "Installation path not found in config. Please reinstall."
exit 1
fi
if [[ ! -d "$install_path" ]]; then
log_error "Installation directory '$install_path' no longer exists. Please reinstall."
exit 1
fi
if [[ ! -f "$install_path/index.php" ]]; then
log_error "Index.php not found at '$install_path'. Please reinstall."
exit 1
fi
if [[ "$current_version" == "$latest_version" ]]; then
log_success "Already up to date (version $current_version)"
return 0
fi
log_info "Current version: $current_version"
log_info "Latest version: $latest_version"
log_info "Installation path: $install_path"
# Backup config files
local backup_path=$(backup_config_files "$install_path")
log_info "Created config backup: $backup_path"
# Download all new files (this will overwrite everything except config.json)
log_info "Downloading updated files..."
download_indexer_files "$install_path"
# Restore config.json if it was backed up
if [[ -f "$backup_path/config.json" ]]; then
sudo cp "$backup_path/config.json" "$install_path/.indexer_files/"
sudo chown www-data:www-data "$install_path/.indexer_files/config.json"
log_info "Restored config.json from backup"
fi
local update_date=$(date '+%Y-%m-%d %H:%M:%S')
save_installation_config "$latest_version" "$install_path" "$update_date"
log_success "Updated from $current_version to $latest_version"
log_info "Config backup available at: $backup_path"
}
show_version() {
local current_version=$(get_current_version)
local latest_version=$(get_latest_version)
local install_path=$(get_installation_path)
echo "5q12's Indexer Version Information"
echo "=================================="
echo "Installed version: $current_version"
echo "Latest version: $latest_version"
if [[ -n "$install_path" ]]; then
echo "Installation path: $install_path"
fi
if [[ -f "$CONFIG_FILE" ]]; then
get_installation_config
if [[ -n "$INDEXER_INSTALL_DATE" ]]; then
echo "Installation date: $INDEXER_INSTALL_DATE"
fi
fi
if [[ "$current_version" != "not installed" && "$current_version" != "$latest_version" ]]; then
echo
log_warning "Update available! Run '$SCRIPT_NAME update' to upgrade."
elif [[ "$current_version" == "$latest_version" ]]; then
echo
log_success "You have the latest version installed."
fi
}
setup_script() {
log_info "Setting up system-wide script access..."
sudo mkdir -p "$CONFIG_DIR"
sudo mkdir -p "$BACKUP_DIR"
sudo cp "$0" "$CONFIG_DIR/install.sh"
sudo chmod +x "$CONFIG_DIR/install.sh"
sudo ln -sf "$CONFIG_DIR/install.sh" "$SYMLINK_PATH"
log_success "Script installed! You can now use '$SCRIPT_NAME <command>'"
}
show_usage() {
echo "5q12's Indexer Installation Script"
echo "Usage: $SCRIPT_NAME <command> [options]"
echo
echo "Commands:"
echo " install <path> Install indexer to specified directory"
echo " update Update existing installation"
echo " version | v Show version information"
echo " help | -h Show this help message"
echo
echo "Examples:"
echo " $SCRIPT_NAME install /var/www/html/files"
echo " $SCRIPT_NAME install www"
echo " $SCRIPT_NAME update"
echo " $SCRIPT_NAME version"
}
main() {
local command="$1"
local install_path="$2"
if [[ ! -f "$SYMLINK_PATH" ]]; then
if check_root; then
setup_script
else
log_warning "Run with sudo to enable system-wide access"
fi
fi
case "$command" in
"install")
if [[ -z "$install_path" ]]; then
log_error "Installation path is required"
echo "Usage: $SCRIPT_NAME install <path>"
exit 1
fi
if ! check_root; then
log_error "Installation requires root privileges. Please run with sudo."
exit 1
fi
local missing_req=($(check_requirements))
install_requirements "${missing_req[@]}"
check_and_install_php_extensions
local absolute_path
absolute_path=$(install_indexer "$install_path" | tail -1)
create_nginx_config "$absolute_path"
log_info "Final system verification:"
log_info "PHP Extensions: $(php -m | grep -E 'json|fileinfo|mbstring|sqlite3|zip|curl|openssl' | tr '\n' ' ')"
;;
"update")
if ! check_root; then
log_error "Update requires root privileges. Please run with sudo."
exit 1
fi
update_indexer
;;
"version"|"v")
show_version
;;
"help"|"-h"|"")
show_usage
;;
*)
log_error "Unknown command: $command"
show_usage
exit 1
;;
esac
}
main "$@"