Last active 14 hours ago

Утилита для управления виртуальными хостами NGINX в системах с организацией конфигурации через sites-available/sites-enabled.

Revision c72762cd65e9ff8cdd64f1fecb1b40ec0ae175b4

vhostmanage.md Raw
#!/bin/bash
VERSION='1.1'

### Конфигурация ###
SEARCH_EXTENSION="*"  # Можно изменить на "*" для поиска всех файлов
SITES_AVAILABLE="/etc/nginx/sites-available"
SITES_ENABLED="/etc/nginx/sites-enabled"
SITES_ORDER_DISABLED_FIRST=1  # 1 - выключенные первыми, 0 - включенные первыми

### Стили вывода ###
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

### Справка ###
show_help() {
    echo ""
    echo -e "${YELLOW}VHostManage version $VERSION${NC}"
    echo -e "(c) Karel Wintersky + Claude Sonnet, 2025-2026"
    echo ""
    echo -e "${YELLOW}Использование:${NC}"
    echo "  vhostmanage                            - Информация о версии и список всех сайтов"
    echo "  vhostmanage list                       - Список всех сайтов"
    echo "  vhostmanage list enabled               - Список только включенных сайтов"
    echo "  vhostmanage list disabled              - Список только выключенных сайтов"
    echo "  vhostmanage enable <site> [link_name]  - Включить сайт"
    echo "  vhostmanage disable <site>             - Выключить сайт"
    echo "  vhostmanage help                       - Показать эту справку"
    echo -e "\n${YELLOW}Настройки:${NC}"
    echo "  Измените SEARCH_EXTENSION в скрипте"
    echo "  Доступные значения: conf (по умолчанию) или * (все файлы)"
}

### Проверка прав ###
check_root() {
    if [ "$(id -u)" -ne 0 ]; then
        echo -e "${RED}ВАЖНО: для выполнения команд enable/disable требуется root (используйте sudo)${NC}" >&2
#        exit 1
    fi
}

### Получить реальный путь из симлинка ###
get_available_path() {
    local enabled_link="$1"
    readlink -f "$enabled_link" | sed "s|^$SITES_AVAILABLE/||"
}

### Поиск конфигов ###
find_configs() {
    local search_pattern="*.$SEARCH_EXTENSION"
    [ "$SEARCH_EXTENSION" = "*" ] && search_pattern="*"
    
    find "$SITES_AVAILABLE" -type f -name "$search_pattern" | while read -r file; do
        echo "${file#$SITES_AVAILABLE/}"
    done
}

### Проверка включен ли сайт ###
is_enabled() {
    local site_path="$1"
    find "$SITES_ENABLED" -type l | while read -r link; do
        if [ "$(get_available_path "$link")" = "$site_path" ]; then
            echo "1"
            return
        fi
    done | grep -q "1"
}

### Получить имя симлинка для сайта ###
get_enabled_name() {
    local site_path="$1"
    find "$SITES_ENABLED" -type l | while read -r link; do
        if [ "$(get_available_path "$link")" = "$site_path" ]; then
            basename "$link"
            return
        fi
    done
}

### Вывод списка ###
list_sites() {
    local filter="$1"  # all, enabled, disabled
    
    if [ "$filter" != "enabled" ] && [ "$filter" != "disabled" ]; then
        filter="all"
    fi
    
    # Собираем сайты в массивы
    local enabled_sites=()
    local disabled_sites=()
    
    while IFS= read -r rel_path; do
        if is_enabled "$rel_path"; then
            enabled_sites+=("$rel_path")
        else
            disabled_sites+=("$rel_path")
        fi
    done < <(find_configs)
    
    # Сортируем массивы
    IFS=$'\n' enabled_sites=($(sort <<<"${enabled_sites[*]}"))
    IFS=$'\n' disabled_sites=($(sort <<<"${disabled_sites[*]}"))
    unset IFS
    
    # Выводим в зависимости от фильтра и порядка
    if [ "$filter" = "all" ]; then
        if [ "$SITES_ORDER_DISABLED_FIRST" -eq 1 ]; then
            # Сначала выключенные
            for rel_path in "${disabled_sites[@]}"; do
                echo -e "${RED}[disabled]${NC} $rel_path"
            done
            for rel_path in "${enabled_sites[@]}"; do
                local enabled_name=$(get_enabled_name "$rel_path")
                local base_name=$(basename "$rel_path")
                if [ "$enabled_name" != "$base_name" ]; then
                    echo -e "${GREEN}[enabled]${NC}  $rel_path (как $enabled_name)"
                else
                    echo -e "${GREEN}[enabled]${NC}  $rel_path"
                fi
            done
        else
            # Сначала включенные
            for rel_path in "${enabled_sites[@]}"; do
                local enabled_name=$(get_enabled_name "$rel_path")
                local base_name=$(basename "$rel_path")
                if [ "$enabled_name" != "$base_name" ]; then
                    echo -e "${GREEN}[enabled]${NC}  $rel_path (как $enabled_name)"
                else
                    echo -e "${GREEN}[enabled]${NC}  $rel_path"
                fi
            done
            for rel_path in "${disabled_sites[@]}"; do
                echo -e "${RED}[disabled]${NC} $rel_path"
            done
        fi
    elif [ "$filter" = "enabled" ]; then
        for rel_path in "${enabled_sites[@]}"; do
            local enabled_name=$(get_enabled_name "$rel_path")
            local base_name=$(basename "$rel_path")
            if [ "$enabled_name" != "$base_name" ]; then
                echo -e "${GREEN}[enabled]${NC}  $rel_path (как $enabled_name)"
            else
                echo -e "${GREEN}[enabled]${NC}  $rel_path"
            fi
        done
    elif [ "$filter" = "disabled" ]; then
        for rel_path in "${disabled_sites[@]}"; do
            echo -e "${RED}[disabled]${NC} $rel_path"
        done
    fi
}

### Включение сайта ###
enable_site() {
    local site_path="$1"
    local link_name="${2:-$(basename "$site_path")}"
    local available_path="$SITES_AVAILABLE/$site_path"
    local enabled_path="$SITES_ENABLED/$link_name"

    if [ ! -f "$available_path" ]; then
        echo -e "${RED}Ошибка: файл $available_path не существует${NC}" >&2
        exit 1
    fi

    if is_enabled "$site_path"; then
        local current_name=$(get_enabled_name "$site_path")
        if [ "$current_name" != "$(basename "$site_path")" ]; then
            echo -e "${YELLOW}Предупреждение: сайт уже включен как $current_name${NC}" >&2
        else
            echo -e "${YELLOW}Предупреждение: сайт уже включен${NC}" >&2
        fi
        return
    fi

    if sudo ln -s "$available_path" "$enabled_path"; then
        if [ "$link_name" != "$(basename "$site_path")" ]; then
            echo -e "${GREEN}Включен: $site_path (как $link_name)${NC}"
        else
            echo -e "${GREEN}Включен: $site_path${NC}"
        fi
        
        if ! sudo nginx -t; then
            echo -e "${RED}Ошибка конфигурации!${NC}" >&2
            rm "$enabled_path"
            exit 1
        fi
        
        sudo systemctl reload nginx
        echo "NGINX перезагружен"
    else
        echo -e "${RED}Ошибка создания симлинка${NC}" >&2
        exit 1
    fi
}

### Выключение сайта ###
disable_site() {
    local site_path="$1"
    local enabled_name=$(get_enabled_name "$site_path")
    local enabled_path="$SITES_ENABLED/$enabled_name"

    if [ -z "$enabled_name" ]; then
        echo -e "${YELLOW}Предупреждение: сайт не включен${NC}" >&2
        return
    fi

    if sudo rm "$enabled_path"; then
        if [ "$enabled_name" != "$(basename "$site_path")" ]; then
            echo -e "${GREEN}Выключен: $enabled_name (ссылался на $site_path)${NC}"
        else
            echo -e "${GREEN}Выключен: $site_path${NC}"
        fi
        
        if ! sudo nginx -t; then
            echo -e "${RED}Ошибка конфигурации!${NC}" >&2
            exit 1
        fi
        
        sudo systemctl reload nginx
        echo "NGINX перезагружен"
    else
        echo -e "${RED}Ошибка удаления симлинка${NC}" >&2
        exit 1
    fi
}

### Вывод информации о версии и списка ###
show_about() {
    echo ""
    echo -e "${YELLOW}VHostManage version $VERSION${NC}"
    echo ""
    list_sites "all"
    echo ""
    echo -e "Use ${YELLOW}vhostmanage help${NC} for help"
}


### Основной код ###
# check_root

case "$1" in
    list)
        list_sites "$2"
        ;;
    enable)
        if [ -z "$2" ]; then
            echo -e "${RED}Укажите имя сайта${NC}" >&2
            show_help
            exit 1
        fi
        enable_site "$2" "$3"
        ;;
    disable)
        if [ -z "$2" ]; then
            echo -e "${RED}Укажите имя сайта${NC}" >&2
            show_help
            exit 1
        fi
        disable_site "$2"
        ;;
    help)
        show_help
        ;;
    "")
        show_about
        ;;
    *)
        echo -e "${RED}Неизвестная команда: $1${NC}" >&2
        echo ""
        show_help
        exit 1
        ;;
esac