#!/bin/bash
clear
set -e
UNINSTALL=false
REINSTALL=false
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_FILE="/tmp/altcor_install_$(date +%Y%m%d_%H%M%S).log"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
while getopts ":ur" opt; do
case $opt in
u) UNINSTALL=true ;;
r) REINSTALL=true ;;
\?)
echo -e "${RED}[Ошибка]${NC} Неизвестный параметр: -$OPTARG" >&2
echo "Использование: $0 [-u] [-r]"
echo " -u Полное удаление"
echo " -r Переустановка (удаление + установка)"
exit 1
;;
esac
done
log_to_file() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"; }
log_success() { echo -e "${GREEN}[Успех]${NC} $1"; log_to_file "SUCCESS: $1"; }
log_error() { echo -e "${RED}[Ошибка]${NC} $1"; log_to_file "ERROR: $1"; }
log_info() { echo -e "${BLUE}[Инфо]${NC} $1"; log_to_file "INFO: $1"; }
log_warning() { echo -e "${YELLOW}[Предупреждение]${NC} $1"; log_to_file "WARNING: $1"; }
log_step() { echo -e "${CYAN}[Шаг]${NC} $1"; log_to_file "STEP: $1"; }
generate_password() {
if command -v openssl >/dev/null 2>&1; then
openssl rand -base64 32 | tr -d "=+/" | cut -c1-16
else
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16
fi
}
check_root() {
if [[ $EUID -ne 0 ]]; then
log_error "Запустите этот скрипт с правами администратора (sudo)."
exit 1
fi
}
detect_distro() {
if [ -f /etc/os-release ]; then
source /etc/os-release
DISTRO="$ID"
FAMILY="$ID_LIKE"
VERSION_ID="${VERSION_ID}"
else
log_error "Не удалось определить дистрибутив."
exit 1
fi
if echo "$DISTRO $FAMILY" | grep -qi "debian\|ubuntu"; then
PKG_MANAGER="apt"
DISTRO_FAMILY="debian"
WEBSERVER_SERVICE="apache2"
WEBROOT="/var/www/html"
APACHE_CONF="/etc/apache2/sites-available/000-default.conf"
WEBSERVER_USER="www-data"
PHP_INI_PATH="/etc/php/8.3/apache2/php.ini"
DB_SOCKET="/var/run/mysqld/mysqld.sock"
elif echo "$DISTRO $FAMILY" | grep -qi "rhel\|centos\|fedora\|rocky\|almalinux"; then
DISTRO_FAMILY="rhel"
WEBSERVER_SERVICE="httpd"
WEBROOT="/var/www/html"
APACHE_CONF="/etc/httpd/conf.d/altcor.conf"
WEBSERVER_USER="apache"
DB_SOCKET="/var/lib/mysql/mysql.sock"
if command -v dnf >/dev/null 2>&1; then
PKG_MANAGER="dnf"
else
PKG_MANAGER="yum"
fi
if [ -f "/etc/opt/remi/php83/php.ini" ]; then
PHP_INI_PATH="/etc/opt/remi/php83/php.ini"
PHP_FPM_CONF="/etc/opt/remi/php83/php-fpm.d/www.conf"
PHP_FPM_SERVICE="php83-php-fpm"
SOCKET_PATH="/var/opt/remi/php83/run/php-fpm/www.sock"
elif [ -f "/etc/php.ini" ]; then
PHP_INI_PATH="/etc/php.ini"
PHP_FPM_CONF="/etc/php-fpm.d/www.conf"
PHP_FPM_SERVICE="php-fpm"
SOCKET_PATH="/run/php-fpm/www.sock"
fi
else
log_error "Дистрибутив '$DISTRO' не поддерживается."
log_info "Поддерживаются: Debian, Ubuntu, CentOS, RHEL, Fedora, Rocky Linux, AlmaLinux"
exit 1
fi
log_info "Обнаружен дистрибутив: $DISTRO ($DISTRO_FAMILY)"
}
safe_execute() {
local description="$1"
shift
log_info "$description..."
if "$@" >/dev/null 2>&1; then
log_success "$description - выполнено"
return 0
else
log_error "$description - не удалось выполнить"
log_to_file "FAILED COMMAND: $*"
return 1
fi
}
check_component_status() {
local component=$1
local command_check=$2
local service_check=$3
if command -v "$command_check" >/dev/null 2>&1; then
if [[ -n "$service_check" ]]; then
if systemctl is-active --quiet "$service_check" 2>/dev/null; then
return 0
else
return 1
fi
else
return 0
fi
else
return 2
fi
}
check_existing_installation() {
log_step "Проверка существующей установки..."
local apache_status php_status mariadb_status redis_status
local need_reinstall=false
log_info "Проверка Apache..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
check_component_status "Apache" "apache2" "apache2"
apache_status=$?
else
check_component_status "Apache" "httpd" "httpd"
apache_status=$?
fi
log_info "Проверка PHP..."
check_component_status "PHP" "php" ""
php_status=$?
log_info "Проверка MariaDB..."
check_component_status "MariaDB" "mysql" "mariadb"
mariadb_status=$?
log_info "Проверка Redis..."
if systemctl is-active --quiet redis-server 2>/dev/null || systemctl is-active --quiet redis 2>/dev/null; then
redis_status=0
elif command -v redis-cli >/dev/null 2>&1; then
redis_status=1
else
redis_status=2
fi
echo ""
display_component_status "Apache" $apache_status
display_php_status $php_status
display_component_status "MariaDB" $mariadb_status
display_component_status "Redis" $redis_status
if [ -f "/var/www/html/db_config.php" ]; then
echo -e "Конфигурация БД: ${GREEN}Найдена${NC}"
else
echo -e "Конфигурация БД: ${RED}Не найдена${NC}"
need_reinstall=true
fi
echo ""
if [[ $apache_status -ne 0 ]] || [[ $php_status -ne 0 ]] || [[ $mariadb_status -ne 0 ]]; then
need_reinstall=true
fi
return $([ "$need_reinstall" = "true" ] && echo 1 || echo 0)
}
display_component_status() {
local name=$1
local status=$2
case $status in
0) echo -e "$name: ${GREEN}Установлен и работает${NC}" ;;
1) echo -e "$name: ${YELLOW}Установлен, но не работает${NC}" ;;
2) echo -e "$name: ${RED}Не установлен${NC}" ;;
esac
}
display_php_status() {
local status=$1
case $status in
0)
local php_version=$(php -v 2>/dev/null | head -1 | cut -d' ' -f2 | cut -d'.' -f1,2 2>/dev/null || echo "неизвестно")
if [[ "$php_version" == "8.3" ]]; then
echo -e "PHP: ${GREEN}Установлен (версия $php_version)${NC}"
else
echo -e "PHP: ${YELLOW}Установлен (версия $php_version, требуется 8.3)${NC}"
return 1
fi
;;
2) echo -e "PHP: ${RED}Не установлен${NC}"; return 1 ;;
esac
return 0
}
full_uninstall() {
log_step "Начинаем полное удаление Altcor..."
log_info "Остановка сервисов..."
for service in nginx apache2 httpd php*-fpm mariadb mysql redis redis-server php83-php-fpm; do
systemctl stop "$service" 2>/dev/null || true
done
log_info "Удаление пакетов..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
export DEBIAN_FRONTEND=noninteractive
for db_package in mariadb-server mysql-server; do
for version in "" "-10.3" "-10.5" "-10.6" "-10.11" "-5.7" "-8.0"; do
echo "${db_package}${version} mysql-server/remove-data-dir boolean true" | debconf-set-selections 2>/dev/null || true
done
done
safe_execute "Удаление пакетов (Debian/Ubuntu)" \
apt purge -y nginx* apache2* php* mariadb* mysql* redis*
safe_execute "Очистка неиспользуемых пакетов" apt autoremove -y
else
safe_execute "Удаление пакетов (RHEL/CentOS/Fedora)" \
$PKG_MANAGER remove -y nginx httpd php* mariadb* mysql* redis*
fi
log_info "Удаление файлов конфигурации и данных..."
rm -rf /etc/nginx /etc/apache2 /etc/httpd /etc/php* /var/www/html/* \
/var/lib/mysql* /var/lib/redis* ~/.mysql_history /root/.mysql_history \
/root/.db_password /etc/opt/remi/php83 /opt/remi/php83 2>/dev/null || true
log_success "Полное удаление завершено."
if [ "$REINSTALL" = false ]; then
exit 0
else
log_info "Переустановка: удаление завершено, продолжаем установку..."
echo ""
fi
}
update_system() {
log_step "Обновление системы и установка базовых пакетов..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
export DEBIAN_FRONTEND=noninteractive
safe_execute "Обновление списка пакетов" apt update -y
safe_execute "Установка базовых пакетов" \
apt install -y software-properties-common lsb-release ca-certificates \
curl wget gnupg2 apt-transport-https unzip
else
safe_execute "Обновление системы" $PKG_MANAGER update -y
safe_execute "Установка EPEL репозитория" $PKG_MANAGER install -y epel-release || true
safe_execute "Установка базовых пакетов" \
$PKG_MANAGER install -y curl wget gnupg2 unzip
fi
}
setup_php_repositories() {
log_step "Настройка репозиториев для PHP 8.3..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
if ! apt-cache show php8.3 &>/dev/null; then
log_info "Добавление репозитория Sury для PHP 8.3..."
if ! curl -fsSL https://packages.sury.org/php/apt.gpg | gpg --dearmor -o /usr/share/keyrings/php-archive-keyring.gpg 2>/dev/null; then
log_warning "Не удалось добавить ключ Sury, пробуем PPA..."
safe_execute "Добавление PPA ondrej/php" add-apt-repository ppa:ondrej/php -y
else
CODENAME=$(lsb_release -cs)
echo "deb [signed-by=/usr/share/keyrings/php-archive-keyring.gpg] https://packages.sury.org/php/ $CODENAME main" > /etc/apt/sources.list.d/php.list
fi
safe_execute "Обновление списка пакетов после добавления репозитория PHP" apt update -y
if ! apt-cache show php8.3 &>/dev/null; then
log_error "PHP 8.3 недоступен после добавления репозиториев"
exit 1
fi
fi
log_success "Репозиторий PHP 8.3 настроен"
else
log_info "Настройка репозиториев Remi для RHEL-семейства..."
local version_id=$(echo "$VERSION_ID" | cut -d'.' -f1)
if [ "$DISTRO" = "fedora" ]; then
local fedora_version=$(rpm -E %fedora)
safe_execute "Установка Remi репозитория для Fedora" \
$PKG_MANAGER install -y "https://rpms.remirepo.net/fedora/remi-release-${fedora_version}.rpm"
else
safe_execute "Установка Remi репозитория для RHEL/CentOS" \
$PKG_MANAGER install -y "https://rpms.remirepo.net/enterprise/remi-release-${version_id}.rpm"
fi
if command -v dnf >/dev/null 2>&1; then
safe_execute "Сброс модуля PHP" dnf module reset php -y || true
safe_execute "Включение модуля PHP 8.3" dnf module enable php:remi-8.3 -y || true
fi
log_success "Репозиторий Remi настроен"
fi
}
install_components() {
log_step "Установка основных компонентов..."
log_info "Остановка конфликтующих сервисов..."
for service in nginx httpd apache2 php*-fpm mariadb mysql; do
systemctl stop "$service" 2>/dev/null || true
done
systemctl disable nginx httpd 2>/dev/null || true
sleep 3
remove_old_packages
if [ "$DISTRO_FAMILY" = "debian" ]; then
safe_execute "Установка Apache" apt install -y apache2
else
safe_execute "Установка Apache (httpd)" $PKG_MANAGER install -y httpd
fi
install_mariadb
install_php83
install_additional_components
}
remove_old_packages() {
log_info "Удаление старых версий пакетов..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
export DEBIAN_FRONTEND=noninteractive
for db_package in mariadb-server mysql-server; do
for version in "" "-10.3" "-10.5" "-10.6" "-10.11" "-5.7" "-8.0"; do
echo "${db_package}${version} mysql-server/remove-data-dir boolean true" | debconf-set-selections 2>/dev/null || true
done
done
apt remove -y nginx nginx-common nginx-core 2>/dev/null || true
apt remove -y php7.* php8.0* php8.1* php8.2* libapache2-mod-php7.* libapache2-mod-php8.0* libapache2-mod-php8.1* libapache2-mod-php8.2* 2>/dev/null || true
apt remove --purge -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" mariadb* mysql* 2>/dev/null || true
apt autoremove -y 2>/dev/null || true
else
$PKG_MANAGER remove -y nginx php php7* php80* php81* php82* mariadb* mysql* 2>/dev/null || true
fi
rm -rf /var/lib/mysql* /etc/mysql* /var/log/mysql* /etc/my.cnf* 2>/dev/null || true
}
install_mariadb() {
log_info "Установка MariaDB..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
export DEBIAN_FRONTEND=noninteractive
echo "mariadb-server mysql-server/root_password password ''" | debconf-set-selections 2>/dev/null || true
echo "mariadb-server mysql-server/root_password_again password ''" | debconf-set-selections 2>/dev/null || true
safe_execute "Установка MariaDB" apt install -y mariadb-server
else
safe_execute "Установка MariaDB" $PKG_MANAGER install -y mariadb-server
fi
safe_execute "Запуск MariaDB" systemctl start mariadb
safe_execute "Включение MariaDB в автозагрузку" systemctl enable mariadb
log_info "Ожидание полного запуска MariaDB..."
local retry_count=0
while ! systemctl is-active --quiet mariadb && [ $retry_count -lt 10 ]; do
sleep 2
((retry_count++))
done
if ! systemctl is-active --quiet mariadb; then
log_error "MariaDB не удалось запустить"
exit 1
fi
}
install_php83() {
log_info "Установка PHP 8.3 и расширений..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
export DEBIAN_FRONTEND=noninteractive
local php_packages="php8.3 php8.3-cli php8.3-common php8.3-mysql php8.3-curl php8.3-gd php8.3-mbstring php8.3-xml php8.3-zip php8.3-opcache php8.3-intl php8.3-bcmath php8.3-json php8.3-readline libapache2-mod-php8.3"
else
if $PKG_MANAGER list available | grep -q "php83-php\b"; then
local php_packages="php83-php php83-php-cli php83-php-common php83-php-mysqlnd php83-php-curl php83-php-gd php83-php-mbstring php83-php-xml php83-php-zip php83-php-opcache php83-php-intl php83-php-bcmath php83-php-json php83-php-fpm"
else
local php_packages="php php-cli php-common php-mysqlnd php-curl php-gd php-mbstring php-xml php-zip php-opcache php-intl php-bcmath php-json php-fpm"
fi
fi
if ! $PKG_MANAGER install -y $php_packages >/dev/null 2>&1; then
log_error "Не удалось установить PHP пакеты. Подробности в логе: $LOG_FILE"
$PKG_MANAGER install -y $php_packages 2>&1 | tee -a "$LOG_FILE"
exit 1
fi
if command -v php83 >/dev/null 2>&1 && [ ! -f /usr/bin/php ]; then
ln -sf /opt/remi/php83/root/usr/bin/php /usr/bin/php 2>/dev/null || true
echo 'export PATH=/opt/remi/php83/root/usr/bin:$PATH' > /etc/profile.d/php83.sh
fi
verify_php_installation
}
verify_php_installation() {
log_info "Проверка установки PHP..."
if ! command -v php >/dev/null 2>&1; then
log_error "PHP не найден после установки"
exit 1
fi
local php_version=$(php -v 2>/dev/null | head -1 | cut -d' ' -f2 | cut -d'.' -f1,2 2>/dev/null || echo "неизвестно")
if [[ "$php_version" != "8.3" ]]; then
log_warning "PHP версия $php_version (ожидалась 8.3)"
if [ "$DISTRO_FAMILY" = "debian" ] && [ -f /usr/bin/php8.3 ]; then
update-alternatives --set php /usr/bin/php8.3 2>/dev/null || true
php_version=$(php -v 2>/dev/null | head -1 | cut -d' ' -f2 | cut -d'.' -f1,2 2>/dev/null || echo "неизвестно")
fi
fi
if [[ "$php_version" == "8.3" ]]; then
log_success "PHP 8.3 успешно установлен"
else
log_error "Не удалось установить PHP 8.3 (текущая версия: $php_version)"
exit 1
fi
verify_php_extensions
}
verify_php_extensions() {
log_info "Проверка PHP расширений..."
local required_extensions="mysqli pdo_mysql curl gd mbstring xml zip opcache intl bcmath json"
local missing_extensions=""
for ext in $required_extensions; do
if php -m 2>/dev/null | grep -q "^$ext$"; then
log_success "Расширение $ext: установлено"
else
log_warning "Расширение $ext: НЕ найдено"
missing_extensions="$missing_extensions $ext"
fi
done
if [ -n "$missing_extensions" ]; then
log_warning "Попытка установки отсутствующих расширений:$missing_extensions"
install_missing_php_extensions "$missing_extensions"
fi
}
install_missing_php_extensions() {
local missing_extensions="$1"
if [ "$DISTRO_FAMILY" = "debian" ]; then
for ext in $missing_extensions; do
if [[ "$ext" =~ ^(mysqli|pdo_mysql)$ ]]; then
apt install -y php8.3-mysql 2>/dev/null || true
else
apt install -y "php8.3-$ext" 2>/dev/null || true
fi
done
else
for ext in $missing_extensions; do
if [[ "$ext" =~ ^(mysqli|pdo_mysql)$ ]]; then
$PKG_MANAGER install -y php*-mysqlnd 2>/dev/null || true
else
$PKG_MANAGER install -y "php*-$ext" 2>/dev/null || true
fi
done
fi
}
install_additional_components() {
log_info "Установка дополнительных компонентов (Redis, LibreOffice, Java)..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
export DEBIAN_FRONTEND=noninteractive
safe_execute "Установка дополнительных компонентов" \
apt install -y redis-server libreoffice default-jre
else
safe_execute "Установка дополнительных компонентов" \
$PKG_MANAGER install -y redis libreoffice java-11-openjdk
fi
}
configure_apache_php() {
log_step "Настройка Apache и PHP..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
configure_apache_debian
else
configure_apache_rhel
fi
configure_php_ini
create_virtual_host
verify_apache_config
}
configure_apache_debian() {
log_info "Настройка Apache для Debian/Ubuntu..."
a2enmod php8.3 rewrite ssl headers expires deflate 2>/dev/null || true
for php_ver in 7.4 8.0 8.1 8.2; do
a2dismod "php$php_ver" 2>/dev/null || true
done
}
configure_apache_rhel() {
log_info "Настройка Apache для RHEL семейства..."
rm -f /etc/httpd/conf.d/php.conf /etc/httpd/conf.modules.d/*php*.conf 2>/dev/null || true
configure_php_fpm
create_php_fpm_config
create_altcor_config
}
configure_php_fpm() {
log_info "Настройка PHP-FPM..."
if [ -z "$PHP_FPM_CONF" ] || [ ! -f "$PHP_FPM_CONF" ]; then
log_error "Файл конфигурации PHP-FPM не найден: $PHP_FPM_CONF"
exit 1
fi
cp "$PHP_FPM_CONF" "${PHP_FPM_CONF}.backup.$(date +%Y%m%d_%H%M%S)"
sed -i "s|;*listen = .*|listen = $SOCKET_PATH|" "$PHP_FPM_CONF"
sed -i 's/;*listen.owner = .*/listen.owner = apache/' "$PHP_FPM_CONF"
sed -i 's/;*listen.group = .*/listen.group = apache/' "$PHP_FPM_CONF"
sed -i 's/;*listen.mode = .*/listen.mode = 0660/' "$PHP_FPM_CONF"
sed -i 's/;*user = .*/user = apache/' "$PHP_FPM_CONF"
sed -i 's/;*group = .*/group = apache/' "$PHP_FPM_CONF"
sed -i 's/;*pm = .*/pm = dynamic/' "$PHP_FPM_CONF"
sed -i 's/;*pm.max_children = .*/pm.max_children = 50/' "$PHP_FPM_CONF"
sed -i 's/;*pm.start_servers = .*/pm.start_servers = 5/' "$PHP_FPM_CONF"
sed -i 's/;*pm.min_spare_servers = .*/pm.min_spare_servers = 5/' "$PHP_FPM_CONF"
sed -i 's/;*pm.max_spare_servers = .*/pm.max_spare_servers = 35/' "$PHP_FPM_CONF"
local socket_dir=$(dirname "$SOCKET_PATH")
mkdir -p "$socket_dir"
chown apache:apache "$socket_dir"
safe_execute "Запуск PHP-FPM" systemctl start "$PHP_FPM_SERVICE"
safe_execute "Включение PHP-FPM в автозагрузку" systemctl enable "$PHP_FPM_SERVICE"
if ! systemctl is-active --quiet "$PHP_FPM_SERVICE"; then
log_error "PHP-FPM не удалось запустить"
systemctl status "$PHP_FPM_SERVICE" --no-pager -l | tee -a "$LOG_FILE"
exit 1
fi
}
create_php_fpm_config() {
log_info "Создание конфигурации PHP-FPM для Apache..."
cat > "/etc/httpd/conf.d/php-fpm.conf" << EOF
# PHP-FPM configuration for Apache
# Использование только PHP-FPM, без mod_php
# Загрузка необходимых модулей