Скрипты.

Установка, настройка, эксплуатация.

Модератор: root

Скрипты.

Сообщение root » 17 сен 2015, 19:45

Оглавление


Темы
 Сервис архивации 
 Чистка каталогов по списку 
 Создание пользователей и баз для MySQL 
 Добавление виртуального хоста APACHE пользователей и баз данных 
 Включение по сети (Wake-on-LAN) 
 Построение файлов зон для DNS-сервера 
 Построение MD5-ХЭШ сумм файлов 
 Примеры монтирования CIFS 
 Синхронизация локального репозитория для CentOS 
 Очистка и переиндексация баз данных Postgres 
 Скрипт для архивирования баз 
 Список активных хостов в сети 
 Тестирование группы хостов на корректность записей в прямой и обратной DNS-зоне 
 Управление виртуальными машинами скриптами 
 NMAP: Сканирование хостов и портов (обёртка) 
 Резервное копирование Файловой системы XFS 
 Перезапуск сервисов после сна 
 Динамическое сообщение дня (motd) 
 Резервное копирование виртуальных машин VirtualBox 
 Переключение виртуальных сред VirtualBox и KVM 
Дополнительные материалы
Wake on Lan: Удалённое включение компьютера


 Сервис архивации 
backup-hosts.sh
Код: выделить все
!/bin/bash

# ============================================================
# Web Hosts Backup Service
# ============================================================

VERSION="3.2"

# ------------------------------------------------------------
# Настройки
# ------------------------------------------------------------

BACKUP_PATH="/mnt/BACKUP/WebHost/"
WEB_DIR="/var/www/"
LOG_FILE="/var/log/backup-hosts.log"
KEEP_BACKUPS=6                      # Количество хранимых бэкапов

# MySQL/MariaDB
MYSQL_CMD="mariadb"                 # или mysql
MYSQLDUMP_CMD="mariadb-dump"        # или mysqldump
MYSQL_USER="root"
MYSQL_PASS="RootMySQL"

LOG_LEVEL=3
USE_SYSLOG=false

# ------------------------------------------------------------
# Проверка: mysql или mariadb?
# ------------------------------------------------------------

function detect_mysql_client() {
    if command -v mariadb &>/dev/null; then
        MYSQL_CMD="mariadb"
        MYSQLDUMP_CMD="mariadb-dump"
        log_debug "Используется MariaDB клиент"
    elif command -v mysql &>/dev/null; then
        MYSQL_CMD="mysql"
        MYSQLDUMP_CMD="mysqldump"
        log_debug "Используется MySQL клиент"
    else
        log_error "MySQL/MariaDB клиент не найден!"
        return 1
    fi
    return 0
}

# ------------------------------------------------------------
# Unicode / ASCII
# ------------------------------------------------------------

if [[ "${1:-}" == "--no-icons" ]]; then
    INFO_ICON=">"
    OK_ICON="+"
    WARN_ICON="!"
    ERR_ICON="x"
    DEBUG_ICON="D"
    STAR_ICON="*"
else
    INFO_ICON="→"
    OK_ICON="✓"
    WARN_ICON="⚠"
    ERR_ICON="✗"
    DEBUG_ICON="•"
    STAR_ICON="★"
fi

# ------------------------------------------------------------
# Переменные
# ------------------------------------------------------------

STATUS="SUCCESS"
LOG_SESSION_ENDED=false
LOG_SESSION_STARTED=false

DATE="$(date '+%d-%m-%Y')"
TIME="$(date '+%H-%M')"
BACKUP_DIR="$BACKUP_PATH/$DATE"

TOTAL_ARCHIVES=0
TOTAL_SIZE=0

# ------------------------------------------------------------
# Логирование
# ------------------------------------------------------------

function _log() {
    local level="$1"; shift
    local message="$*"
    local timestamp

    timestamp="$(date '+%Y-%m-%d %H:%M:%S')"

    local level_num level_tag color_tag color_reset

    case "$level" in
        ERROR) level_num=1; level_tag="${ERR_ICON} ERROR"; color_tag="\033[1;31m" ;;
        WARN)  level_num=2; level_tag="${WARN_ICON} WARN "; color_tag="\033[1;33m" ;;
        INFO)  level_num=3; level_tag="${INFO_ICON} INFO "; color_tag="\033[1;34m" ;;
        OK)    level_num=3; level_tag="${OK_ICON} OK   ";  color_tag="\033[1;32m" ;;
        DEBUG) level_num=4; level_tag="${DEBUG_ICON} DEBUG"; color_tag="\033[0;90m" ;;
        *)     level_num=3; level_tag="INFO"; color_tag="\033[0m" ;;
    esac

    color_reset="\033[0m"

    # Запись в лог-файл
    echo "[$timestamp] [$level_tag] $message" >> "$LOG_FILE"

    # Запись в syslog
    if [[ "$USE_SYSLOG" == true ]]; then
        logger -t "$(basename "$0")" "[$level] $message"
    fi

    # Вывод в консоль
    if (( level_num <= LOG_LEVEL )); then
        if [[ -t 1 ]]; then
            echo -e "${color_tag}[$timestamp] [$level_tag]${color_reset} $message"
        else
            echo "[$timestamp] [$level_tag] $message"
        fi
    fi
}

log_info()  { _log INFO  "$@"; }
log_warn()  { _log WARN  "$@"; }
log_error() { _log ERROR "$@"; }
log_ok()    { _log OK    "$@"; }
log_debug() { _log DEBUG "$@"; }

# ------------------------------------------------------------
# Session Log
# ------------------------------------------------------------

function log_session_start() {
    local line="START | MODE: WEB_BACKUP | VERSION: $VERSION"
    local width=60
    local padding=$(( (width - ${#line}) / 2 ))

    {
        printf '=%.0s' $(seq 1 $width)
        printf "\n%*s%s\n" "$padding" "" "$line"
        printf '=%.0s' $(seq 1 $width)
        echo
        echo
    } >> "$LOG_FILE"

    echo
    printf '=%.0s' $(seq 1 $width)
    printf "\n%*s%s\n" "$padding" "" "$line"
    printf '=%.0s' $(seq 1 $width)
    echo
    echo

    LOG_SESSION_STARTED=true
}

function log_session_end() {
    local status="$1"

    local line="END | STATUS: $status"
    local width=60
    local padding=$(( (width - ${#line}) / 2 ))

    {
        echo
        printf '=%.0s' $(seq 1 $width)
        echo
        printf "%*s%s\n" "$padding" "" "$line"
        printf '=%.0s' $(seq 1 $width)
        echo
    } >> "$LOG_FILE"

    echo
    printf '=%.0s' $(seq 1 $width)
    echo
    printf "%*s%s\n" "$padding" "" "$line"
    printf '=%.0s' $(seq 1 $width)
    echo

    LOG_SESSION_ENDED=true
}

# ------------------------------------------------------------
# Cleanup
# ------------------------------------------------------------

cleanup() {
    if [[ "$LOG_SESSION_ENDED" == false ]]; then
        log_session_end "$STATUS"
    fi
}

trap cleanup EXIT
trap 'STATUS="FAILED"; exit 1' INT TERM

# ------------------------------------------------------------
# Header
# ------------------------------------------------------------

log_session_start

log_info "Скрипт: $(basename "$0")"
log_info "Версия: $VERSION"
log_info "Каталог бэкапов: $BACKUP_DIR"

# ------------------------------------------------------------
# Проверка зависимостей
# ------------------------------------------------------------

function check_dependencies() {
    local deps=("tar" "find" "du" "awk")
    local missing=()

    for dep in "${deps[@]}"; do
        if ! command -v "$dep" &>/dev/null; then
            missing+=("$dep")
        fi
    done

    # Проверка MySQL/MariaDB
    if ! detect_mysql_client; then
        missing+=("mariadb/mysql")
    fi

    if [[ ${#missing[@]} -gt 0 ]]; then
        log_error "Отсутствуют зависимости: ${missing[*]}"
        return 1
    fi

    log_ok "Все зависимости установлены"
    return 0
}

# ------------------------------------------------------------
# Форматирование размера
# ------------------------------------------------------------

function format_size() {
    local size="$1"

    if [[ -z "$size" ]] || [[ "$size" -eq 0 ]]; then
        echo "0 B"
        return
    fi

    if [[ "$size" -gt 1073741824 ]]; then
        echo "$(echo "scale=2; $size/1073741824" | bc 2>/dev/null || echo "0") GB"
    elif [[ "$size" -gt 1048576 ]]; then
        echo "$(echo "scale=2; $size/1048576" | bc 2>/dev/null || echo "0") MB"
    elif [[ "$size" -gt 1024 ]]; then
        echo "$(echo "scale=2; $size/1024" | bc 2>/dev/null || echo "0") KB"
    else
        echo "${size} B"
    fi
}

# ------------------------------------------------------------
# Создание каталогов
# ------------------------------------------------------------

function create_directories() {
    local backup_dir="$1"

    log_info "Создание структуры каталогов..."

    if [[ ! -d "$backup_dir" ]]; then
        mkdir -p "$backup_dir"/{WWW,SQL,USERS,SYS} 2>/dev/null
        log_ok "Создана структура: $backup_dir"
    else
        log_warn "Каталог уже существует: $backup_dir"
    fi
}

# ------------------------------------------------------------
# Проверка свободного места
# ------------------------------------------------------------

function check_free_space() {
    local backup_dir="$1"
    local required_gb="$2"

    if [[ ! -d "$backup_dir" ]]; then
        mkdir -p "$backup_dir"
    fi

    local free_space=$(df "$backup_dir" | awk 'NR==2 {print $4}')
    local free_gb=$((free_space / 1024 / 1024))

    log_info "Свободно на диске: ${free_gb} GB"

    if [[ "$free_gb" -lt "$required_gb" ]]; then
        log_error "Недостаточно места! Требуется ~${required_gb} GB, доступно ${free_gb} GB"
        return 1
    fi

    log_ok "Места достаточно"
    return 0
}

# ------------------------------------------------------------
# Бэкап WEB-хостов
# ------------------------------------------------------------

function backup_web_hosts() {
    local web_dir="$1"
    local backup_dir="$2"
    local time="$3"

    log_info "Бэкап WEB-хостов..."

    if [[ ! -d "$web_dir" ]]; then
        log_error "Каталог не существует: $web_dir"
        return 1
    fi

    local dirs=($(find "$web_dir" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' 2>/dev/null))

    if [[ ${#dirs[@]} -eq 0 ]]; then
        log_warn "Нет хостов для бэкапа"
        return 0
    fi

    local count=0

    for dir in "${dirs[@]}"; do
        if [[ "$dir" =~ ^[a-zA-Z] ]]; then
            if [[ -d "$web_dir/$dir" ]]; then
                local archive_name="${time}.${dir}.tar.gz"
                local archive_path="$backup_dir/WWW/$archive_name"

                log_debug "  Архивирование: $dir"

                if tar -czpf "$archive_path" -C "$web_dir" "$dir" 2>/dev/null; then
                    local size=$(stat -c%s "$archive_path" 2>/dev/null || echo 0)
                    ((count++))
                    ((TOTAL_ARCHIVES++))
                    ((TOTAL_SIZE += size))
                    log_ok "    $archive_name ($(format_size $size))"
                else
                    log_error "    Ошибка создания архива: $dir"
                fi
            fi
        fi
    done

    log_info "Заархивировано хостов: $count"
}

# ------------------------------------------------------------
# Бэкап баз данных
# ------------------------------------------------------------

function backup_databases() {
    local backup_dir="$1"
    local time="$2"

    log_info "Бэкап баз данных MySQL/MariaDB..."

    # Получаем список баз данных
    local databases=$($MYSQL_CMD --user="$MYSQL_USER" --password="$MYSQL_PASS" -e "SHOW DATABASES;" 2>/dev/null | tr -d "| " | grep -v "Database" | grep -v "information_schema" | grep -v "performance_schema" | grep -v "mysql" | grep -v "sys")

    if [[ -z "$databases" ]]; then
        log_warn "Нет баз данных для бэкапа"
        return 0
    fi

    local count=0

    for db in $databases; do
        if [[ "$db" =~ ^[a-zA-Z] ]]; then
            local dump_name="${time}.${db}.sql"
            local dump_path="$backup_dir/SQL/$dump_name"

            log_debug "  Дамп базы: $db"

            if $MYSQLDUMP_CMD --user="$MYSQL_USER" --password="$MYSQL_PASS" -c -e -B "$db" > "$dump_path" 2>/dev/null; then
                local size=$(stat -c%s "$dump_path" 2>/dev/null || echo 0)
                ((count++))
                ((TOTAL_ARCHIVES++))
                ((TOTAL_SIZE += size))
                log_ok "    $dump_name ($(format_size $size))"
            else
                log_error "    Ошибка дампа базы: $db"
            fi
        fi
    done

    log_info "Заархивировано баз данных: $count"
}

# ------------------------------------------------------------
# Бэкап системных файлов
# ------------------------------------------------------------

function backup_system_files() {
    local backup_dir="$1"
    local time="$2"

    log_info "Бэкап системных файлов..."

    declare -A sys_dirs=(
        ["named"]="/var/named"
        ["etc"]="/etc"
        ["services"]="/usr/lib/systemd/system"
        ["my-script"]="/sbin/my-script"
        ["efi"]="/boot/efi"
        ["tftp"]="/var/lib/tftpboot"
    )

    local count=0

    for name in "${!sys_dirs[@]}"; do
        local source_dir="${sys_dirs[$name]}"
        local archive_name="${time}.${name}.tar.gz"
        local archive_path="$backup_dir/SYS/$archive_name"

        if [[ -d "$source_dir" ]]; then
            log_debug "  Архивирование: $name ($source_dir)"

            if tar -czpf "$archive_path" -C "$source_dir" . 2>/dev/null; then
                local size=$(stat -c%s "$archive_path" 2>/dev/null || echo 0)
                ((count++))
                ((TOTAL_ARCHIVES++))
                ((TOTAL_SIZE += size))
                log_ok "    $archive_name ($(format_size $size))"
            else
                log_warn "    Ошибка архивирования: $name"
            fi
        else
            log_debug "    Пропуск (нет каталога): $source_dir"
        fi
    done

    log_info "Заархивировано системных каталогов: $count"
}

# ------------------------------------------------------------
# Бэкап пользовательских файлов
# ------------------------------------------------------------

function backup_user_files() {
    local backup_dir="$1"
    local time="$2"

    log_info "Бэкап пользовательских файлов..."

    declare -A user_items=(
        ["doc"]="/root/doc"
        ["scripts"]="/root/SH"
        ["conky"]="/home/serg/.conky"
        ["FilterRules"]="/home/serg/.thunderbird/3l1n9p02.default/ImapMail/imap.gmail.com/msgFilterRules.dat"
    )

    local count=0

    for name in "${!user_items[@]}"; do
        local source="${user_items[$name]}"
        local archive_name="${time}.${name}.tar.gz"
        local archive_path="$backup_dir/USERS/$archive_name"

        if [[ -e "$source" ]]; then
            log_debug "  Архивирование: $name ($source)"

            if [[ -f "$source" ]]; then
                local dir=$(dirname "$source")
                local file=$(basename "$source")
                if tar -czpf "$archive_path" -C "$dir" "$file" 2>/dev/null; then
                    local size=$(stat -c%s "$archive_path" 2>/dev/null || echo 0)
                    ((count++))
                    ((TOTAL_ARCHIVES++))
                    ((TOTAL_SIZE += size))
                    log_ok "    $archive_name ($(format_size $size))"
                else
                    log_warn "    Ошибка архивирования файла: $source"
                fi
            else
                if tar -czpf "$archive_path" -C "$source" . 2>/dev/null; then
                    local size=$(stat -c%s "$archive_path" 2>/dev/null || echo 0)
                    ((count++))
                    ((TOTAL_ARCHIVES++))
                    ((TOTAL_SIZE += size))
                    log_ok "    $archive_name ($(format_size $size))"
                else
                    log_warn "    Ошибка архивирования каталога: $source"
                fi
            fi
        else
            log_debug "    Пропуск (не существует): $source"
        fi
    done

    log_info "Заархивировано пользовательских файлов: $count"
}

# ------------------------------------------------------------
# Ротация старых бэкапов
# ------------------------------------------------------------

function rotate_backups() {
    local backup_root="$1"
    local keep_count="$2"

    log_info "Ротация бэкапов (хранить $keep_count)..."

    if [[ ! -d "$backup_root" ]]; then
        log_info "Каталог бэкапов не существует"
        return 0
    fi

    local dirs=($(find "$backup_root" -maxdepth 1 -type d ! -path "$backup_root" -printf '%T@ %f\n' 2>/dev/null | sort -n | awk '{print $2}'))

    local total=${#dirs[@]}

    if [[ "$total" -le "$keep_count" ]]; then
        log_info "Бэкапов: $total (не превышает $keep_count)"
        return 0
    fi

    local to_delete=$((total - keep_count))
    local deleted=0
    local deleted_size=0

    for ((i=0; i<to_delete; i++)); do
        local dir="$backup_root/${dirs[$i]}"
        if [[ -d "$dir" ]]; then
            local size=$(du -sb "$dir" 2>/dev/null | awk '{print $1}')
            rm -rf "$dir"
            ((deleted++))
            ((deleted_size += size))
            log_debug "Удалён бэкап: $(basename "$dir")"
        fi
    done

    log_ok "Удалено $deleted старых бэкапов ($(format_size $deleted_size))"
}

# ------------------------------------------------------------
# Главная функция
# ------------------------------------------------------------

function main() {
    log_info "Запуск резервного копирования WEB-хостов..."

    if ! check_dependencies; then
        STATUS="FAILED"
        return 1
    fi

    if ! check_free_space "$BACKUP_PATH" 2; then
        STATUS="FAILED"
        return 1
    fi

    create_directories "$BACKUP_DIR"

    backup_web_hosts "$WEB_DIR" "$BACKUP_DIR" "$TIME"

    backup_databases "$BACKUP_DIR" "$TIME"

    backup_system_files "$BACKUP_DIR" "$TIME"

    backup_user_files "$BACKUP_DIR" "$TIME"

    echo
    echo "${STAR_ICON} ${STAR_ICON} ${STAR_ICON} ИТОГИ БЭКАПА ${STAR_ICON} ${STAR_ICON} ${STAR_ICON}"
    echo "  ${INFO_ICON} Создано архивов: $TOTAL_ARCHIVES"
    echo "  ${SIZE_ICON} Общий размер: $(format_size $TOTAL_SIZE)"
    echo "  ${INFO_ICON} Каталог: $BACKUP_DIR"
    echo

    log_ok "Бэкап завершён успешно"

    rotate_backups "$BACKUP_PATH" "$KEEP_BACKUPS"

    return 0
}

# ------------------------------------------------------------
# Справка
# ------------------------------------------------------------

function show_help() {
    cat << EOF

${STAR_ICON} ${STAR_ICON} ${STAR_ICON} WEB HOSTS BACKUP SERVICE ${STAR_ICON} ${STAR_ICON} ${STAR_ICON}

Назначение: Резервное копирование WEB-хостов, БД MySQL/MariaDB и системных файлов

Использование: $(basename "$0") [ОПЦИИ]

Опции:

    -b, --backup          Создать бэкап (действие по умолчанию)
    -c, --clean           Только очистить старые бэкапы
    -k, --keep N          Хранить N последних бэкапов (по умолчанию: 6)
    -p, --path ПУТЬ       Каталог для бэкапов (по умолчанию: $BACKUP_PATH)
    --no-icons            Отключить иконки

    -h, --help            Показать эту справку
    -v, --version         Показать версию

Примеры:

    # Создать бэкап
    $(basename "$0")

    # Создать бэкап с хранением 10 копий
    $(basename "$0") -k 10

    # Только очистить старые бэкапы
    $(basename "$0") -c

    # Указать другой каталог
    $(basename "$0") -p /mnt/backup/web

EOF
}

# ------------------------------------------------------------
# Версия
# ------------------------------------------------------------

function show_version() {
    echo "Web Hosts Backup Service"
    echo "Версия $VERSION"
    echo "© SSERGEY  Дата: 11.11.2017 (обновлено: 2026)"
}

# ------------------------------------------------------------
# Обработка аргументов
# ------------------------------------------------------------

CLEAN_ONLY=false

while [[ $# -gt 0 ]]; do
    case "$1" in
        -b|--backup)
            shift
            ;;
        -c|--clean)
            CLEAN_ONLY=true
            shift
            ;;
        -k|--keep)
            KEEP_BACKUPS="$2"
            shift 2
            ;;
        -p|--path)
            BACKUP_PATH="$2"
            shift 2
            ;;
        --no-icons)
            shift
            ;;
        -h|--help)
            show_help
            log_session_end "HELP"
            exit 0
            ;;
        -v|--version)
            show_version
            log_session_end "VERSION"
            exit 0
            ;;
        *)
            log_error "Неизвестный параметр: $1"
            show_help
            STATUS="FAILED"
            exit 1
            ;;
    esac
done

# ------------------------------------------------------------
# Проверка прав
# ------------------------------------------------------------

if [[ $EUID -ne 0 ]]; then
    log_error "Требуются права суперпользователя!"
    log_info "Попробуйте: sudo $(basename "$0") $*"
    STATUS="FAILED"
    exit 1
fi

# ------------------------------------------------------------
# Основная логика
# ------------------------------------------------------------

if [[ "$CLEAN_ONLY" == true ]]; then
    rotate_backups "$BACKUP_PATH" "$KEEP_BACKUPS"
    log_ok "Очистка завершена"
    exit 0
fi

if main; then
    log_ok "Скрипт завершил работу"
else
    STATUS="FAILED"
    exit 1
fi

# ------------------------------------------------------------
# Итог
# ------------------------------------------------------------

log_info "Скрипт: $(basename "$0")"

exit 0



 Подготавливаем скрипт к работе в режиме демона по расписанию 
e /etc/systemd/system/backup-hosts.service
Код: выделить все
[Unit]
Description=Backup Apache virtual hosts & MySQL databases (serg)

[Service]
Type=oneshot
ExecStart=/sbin/my-script/backup-hosts.sh
StandardOutput=journal

cat /etc/systemd/system/backup-hosts.timer
Код: выделить все
[Unit]
Description=Run on 21:55 Backup Apache virtual hosts & MySQL databases (serg)


[Timer]
OnCalendar=Mon *-*-* 21:55:00
# Принудительно запустится единожды, если отсутствует последнее время запуска, например, в связи с отключением системы:
#Persistent=true
Unit=backup-hosts.service

[Install]
WantedBy=timers.target

Запуск сервиса
Код: выделить все
systemctl enable --now backup-hosts.timer

Enable для задания означает то, что оно появится в списке заданий, --now - включит задание в работу

Пример задания на ротацию логов в systemd
cat /etc/systemd/system/logrotate.timer
Код: выделить все
[Unit]
Description=Run on 23:59 Rotate log files

[Timer]
OnCalendar=23:59
Persistent=true

[Install]
WantedBy=timers.target

cat /etc/systemd/system/logrotate.service
Код: выделить все
[Unit]
Description=Rotate log files

[Service]
Type=oneshot
ExecStart=/sbin/my-script/logrotate
StandardOutput=rsyslog

Не забываем снести задание в CRON
Последний раз редактировалось root 04 сен 2026, 02:48, всего редактировалось 3 раз(а).
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 09 апр 2022, 19:30



 Чистка каталогов по списку 
cat deldir.sh
Код: выделить все
#!/bin/bash
##############################################
# Чистка старых логов в перечисленных
# каталогах с указанием маски
# /var/log/audit/*log.*
# Составлено: SSERGEY
# Дата: 01.10.2015 v1.0
#############################################

BASE_PATH="$(dirname $(readlink -f $0))"
file="$BASE_PATH/deldir.txt"
n=0
echo "==========================================="
while read line
do
    case $line in
    [\/]* )
    #rm -f  $line
    ((++n))
    ;;
    esac
done < $file

echo "Очищено $n каталогов перечисленных в $file"
echo "==========================================="

cat deldir.txt
Код: выделить все
/var/log/audit/*log.*
/var/log/btmp-*
/var/log/cron-*
/var/log/maillog-*
/var/log/secure-*
/var/log/spooler-*
/var/log/samba/old/*
/var/log/httpd/*-*
/var/log/tuned/*log.*
/var/log/cacti/*.gz
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

#

Сообщение root » 09 апр 2022, 19:31



 Создание пользователей и баз для MySQL 
Функция перенесена в скрипт виртуальных хостов
Последний раз редактировалось root 04 сен 2026, 02:46, всего редактировалось 2 раз(а).
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

#

Сообщение root » 09 апр 2022, 19:33



 Добавление виртуального хоста APACHE
пользователей и баз данных
 
cat apache-add-vh.sh
Код: выделить все
#!/bin/bash

# ============================================================
# Apache Virtual Host + MySQL User Creator
# ============================================================

VERSION="2.1"

# ------------------------------------------------------------
# Настройки
# ------------------------------------------------------------

WEBROOT="/var/www"
VHOST_AVAILABLE="/etc/httpd/sites-available"
VHOST_ENABLED="/etc/httpd/sites-enabled"
DOMAIN_SUFFIX="free-adm.ru"

IP_WHITELIST="127.0.0.1 195.0.1.0/24"
IP6_WHITELIST="::1 2a11:6c7:1202:6200::3"

PHP_FPM_SOCKET="/run/php-fpm/next.free-adm.ru.sock"  # Заглушка, будет заменяться

LOG_LEVEL=3
USE_SYSLOG=false

# ------------------------------------------------------------
# Unicode / ASCII
# ------------------------------------------------------------

if [[ "${1:-}" == "--no-icons" ]]; then
    INFO_ICON=">"
    OK_ICON="+"
    WARN_ICON="!"
    ERR_ICON="x"
    DEBUG_ICON="D"
    STAR_ICON="*"
else
    INFO_ICON="→"
    OK_ICON="✓"
    WARN_ICON="⚠"
    ERR_ICON="✗"
    DEBUG_ICON="•"
    STAR_ICON="★"
fi

# ------------------------------------------------------------
# Переменные
# ------------------------------------------------------------

STATUS="SUCCESS"
LOG_SESSION_ENDED=false
LOG_SESSION_STARTED=false

LOG_FILE="/tmp/vhost-creator.log"
PASS_FILE="/root/.mysql_creds.txt"

HOSTNAME=""
DB_NAME=""
DB_USER=""
DB_PASS=""
PHP_VERSION="8.2"  # или 8.3, 8.4

# ------------------------------------------------------------
# Логирование
# ------------------------------------------------------------

function _log() {
    local level="$1"; shift
    local message="$*"
    local timestamp

    timestamp="$(date '+%Y-%m-%d %H:%M:%S')"

    local level_num level_tag color_tag color_reset

    case "$level" in
        ERROR) level_num=1; level_tag="${ERR_ICON} ERROR"; color_tag="\033[1;31m" ;;
        WARN)  level_num=2; level_tag="${WARN_ICON} WARN "; color_tag="\033[1;33m" ;;
        INFO)  level_num=3; level_tag="${INFO_ICON} INFO "; color_tag="\033[1;34m" ;;
        OK)    level_num=3; level_tag="${OK_ICON} OK   ";  color_tag="\033[1;32m" ;;
        DEBUG) level_num=4; level_tag="${DEBUG_ICON} DEBUG"; color_tag="\033[0;90m" ;;
        *)     level_num=3; level_tag="INFO"; color_tag="\033[0m" ;;
    esac

    color_reset="\033[0m"

    echo "[$timestamp] [$level_tag] $message" >> "$LOG_FILE"

    if (( level_num <= LOG_LEVEL )); then
        if [[ -t 1 ]]; then
            echo -e "${color_tag}[$timestamp] [$level_tag]${color_reset} $message"
        else
            echo "[$timestamp] [$level_tag] $message"
        fi
    fi
}

log_info()  { _log INFO  "$@"; }
log_warn()  { _log WARN  "$@"; }
log_error() { _log ERROR "$@"; }
log_ok()    { _log OK    "$@"; }
log_debug() { _log DEBUG "$@"; }

# ------------------------------------------------------------
# Session Log
# ------------------------------------------------------------

function log_session_start() {
    local line="START | MODE: VHOST_CREATOR | VERSION: $VERSION"
    local width=60
    local padding=$(( (width - ${#line}) / 2 ))

    printf '=%.0s' $(seq 1 $width)
    printf "\n%*s%s\n" "$padding" "" "$line"
    printf '=%.0s' $(seq 1 $width)
    echo
    echo

    LOG_SESSION_STARTED=true
}

function log_session_end() {
    local status="$1"

    local line="END | STATUS: $status"
    local width=60
    local padding=$(( (width - ${#line}) / 2 ))

    echo
    printf '=%.0s' $(seq 1 $width)
    echo
    printf "%*s%s\n" "$padding" "" "$line"
    printf '=%.0s' $(seq 1 $width)
    echo

    LOG_SESSION_ENDED=true
}

# ------------------------------------------------------------
# Cleanup
# ------------------------------------------------------------

cleanup() {
    if [[ "$LOG_SESSION_ENDED" == false ]]; then
        log_session_end "$STATUS"
    fi
}

trap cleanup EXIT
trap 'STATUS="FAILED"; exit 1' INT TERM

# ------------------------------------------------------------
# Header
# ------------------------------------------------------------

log_session_start

log_info "Скрипт: $(basename "$0")"
log_info "Версия: $VERSION"

# ------------------------------------------------------------
# Проверка прав
# ------------------------------------------------------------

function check_permissions() {
    if [[ $EUID -ne 0 ]]; then
        log_error "Требуются права суперпользователя!"
        log_info "Попробуйте: sudo $(basename "$0") $*"
        return 1
    fi
    return 0
}

# ------------------------------------------------------------
# Проверка зависимостей
# ------------------------------------------------------------

function check_dependencies() {
    local deps=("httpd" "mysql" "mariadb" "php-fpm")
    local missing=()

    for dep in "${deps[@]}"; do
        if ! command -v "$dep" &>/dev/null; then
            missing+=("$dep")
        fi
    done

    if [[ ${#missing[@]} -gt 0 ]]; then
        log_warn "Отсутствуют некоторые зависимости: ${missing[*]}"
        log_info "Установите: dnf install httpd php-fpm mariadb-server"
    fi

    log_ok "Основные зависимости установлены"
    return 0
}

# ------------------------------------------------------------
# Определение версии PHP
# ------------------------------------------------------------

function detect_php_version() {
    local php_versions=("8.4" "8.3" "8.2" "8.1" "8.0" "7.4")

    for ver in "${php_versions[@]}"; do
        if command -v "php${ver}" &>/dev/null; then
            PHP_VERSION="$ver"
            log_debug "Найдена версия PHP: $ver"
            return 0
        fi
    done

    log_warn "Не удалось определить версию PHP, использую 8.2 по умолчанию"
    return 0
}

# ------------------------------------------------------------
# Создание конфига виртуального хоста (с SSL)
# ------------------------------------------------------------

function create_vhost_config() {
    local hostname="$1"
    local full_hostname="${hostname}.${DOMAIN_SUFFIX}"
    local vhost_file="$VHOST_AVAILABLE/${full_hostname}.conf"
    local php_socket="/run/php-fpm/${full_hostname}.sock"

    log_info "Создание конфига виртуального хоста: $full_hostname (с SSL)"

    if [[ -f "$vhost_file" ]]; then
        log_warn "Конфиг уже существует: $vhost_file"
        echo -n "Перезаписать? (y/N): "
        read -r confirm
        if [[ "$confirm" != "y" ]] && [[ "$confirm" != "Y" ]]; then
            log_info "Создание конфига отменено"
            return 1
        fi
        mv "$vhost_file" "${vhost_file}.bak.$(date +%Y%m%d_%H%M%S)"
        log_info "Старый конфиг сохранён как бэкап"
    fi

    cat > "$vhost_file" << EOF
# ============================================================
# Виртуальный хост: ${full_hostname}
# Создан: $(date '+%Y-%m-%d %H:%M:%S')
# ============================================================

<VirtualHost *:80>
    ServerName ${full_hostname}
    DocumentRoot ${WEBROOT}/${full_hostname}/public_html

    ErrorLog ${WEBROOT}/${full_hostname}/log/error.log
    CustomLog ${WEBROOT}/${full_hostname}/log/requests.log combined

    <Directory "${WEBROOT}/${full_hostname}/public_html">
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All

        <IfModule mod_authz_core.c>
            <RequireAny>
                Require ip ${IP_WHITELIST}
                Require ip ${IP6_WHITELIST}
            </RequireAny>
        </IfModule>
    </Directory>

    # Автоматический редирект на HTTPS
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

</VirtualHost>

<VirtualHost *:443>
    ServerName ${full_hostname}
    DocumentRoot "${WEBROOT}/${full_hostname}/public_html"

    ErrorLog "${WEBROOT}/${full_hostname}/log/error_ssl.log"
    TransferLog "${WEBROOT}/${full_hostname}/log/access_ssl.log"
    CustomLog "${WEBROOT}/${full_hostname}/log/ssl_request.log" "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

    Include "/etc/httpd/conf/ssl_common.conf"

    <FilesMatch "\\.(cgi|shtml|phtml|php)\$">
        SSLOptions +StdEnvVars
    </FilesMatch>

    <Directory "${WEBROOT}/${full_hostname}/public_html">
        SSLOptions +StdEnvVars
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All

        <IfModule mod_authz_core.c>
            <RequireAny>
                Require ip ${IP_WHITELIST}
                Require ip ${IP6_WHITELIST}
            </RequireAny>
        </IfModule>
    </Directory>

    BrowserMatch "MSIE [2-5]" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0

    # PHP-FPM через Unix-socket (для каждого хоста свой)
    <FilesMatch \\.php\$>
        SetHandler "proxy:unix:${php_socket}|fcgi://localhost"
    </FilesMatch>

    # Настройки PHP (чтобы SetEnv не перезаписывал сам себя)
    SetEnv PHP_ADMIN_VALUE "upload_tmp_dir ${WEBROOT}/${full_hostname}/tmp"
    SetEnv PHP_ADMIN_VALUE "error_log ${WEBROOT}/${full_hostname}/log/php.log"
    SetEnv PHP_ADMIN_VALUE "session.save_path ${WEBROOT}/${full_hostname}/sess"
    SetEnv PHP_ADMIN_VALUE "doc_root ${WEBROOT}/${full_hostname}/public_html"
    SetEnv PHP_ADMIN_VALUE "open_basedir ${WEBROOT}/${full_hostname}/public_html"

</VirtualHost>
EOF

    log_ok "Конфиг создан: $vhost_file"
    echo "$full_hostname"
    return 0
}

# ------------------------------------------------------------
# Создание пула PHP-FPM
# ------------------------------------------------------------

function create_php_fpm_pool() {
    local full_hostname="$1"
    local php_pool_file="/etc/php-fpm.d/${full_hostname}.conf"

    log_info "Создание пула PHP-FPM: $full_hostname"

    if [[ -f "$php_pool_file" ]]; then
        log_warn "Пул PHP-FPM уже существует: $php_pool_file"
        return 0
    fi

    cat > "$php_pool_file" << EOF
[${full_hostname}]
user = apache
group = apache
listen = /run/php-fpm/${full_hostname}.sock
listen.owner = apache
listen.group = apache
listen.mode = 0660

pm = dynamic
pm.max_children = 10
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 6

php_admin_value[upload_tmp_dir] = ${WEBROOT}/${full_hostname}/tmp
php_admin_value[error_log] = ${WEBROOT}/${full_hostname}/log/php.log
php_admin_value[session.save_path] = ${WEBROOT}/${full_hostname}/sess
php_admin_value[doc_root] = ${WEBROOT}/${full_hostname}/public_html
php_admin_value[open_basedir] = ${WEBROOT}/${full_hostname}/public_html
EOF

    chmod 644 "$php_pool_file"
    log_ok "Пул PHP-FPM создан: $php_pool_file"
    return 0
}

# ------------------------------------------------------------
# Создание структуры каталогов
# ------------------------------------------------------------

function create_directory_structure() {
    local full_hostname="$1"
    local host_root="${WEBROOT}/${full_hostname}"

    log_info "Создание структуры каталогов: $host_root"

    if [[ -d "$host_root" ]]; then
        log_warn "Каталог уже существует: $host_root"
        return 0
    fi

    mkdir -p "$host_root"/{sess,log,tmp,public_html} 2>/dev/null
    chown -R apache:apache "$host_root" 2>/dev/null

    log_ok "Структура создана: $host_root"
    return 0
}

# ------------------------------------------------------------
# Создание index.html
# ------------------------------------------------------------

function create_index_html() {
    local full_hostname="$1"
    local index_file="${WEBROOT}/${full_hostname}/public_html/index.html"

    log_info "Создание index.html"

    cat > "$index_file" << EOF
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Welcome to ${full_hostname}</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            max-width: 800px;
            margin: 50px auto;
            padding: 20px;
            background: #f5f5f5;
            color: #333;
        }
        h1 {
            color: #2c3e50;
            border-bottom: 3px solid #3498db;
            padding-bottom: 10px;
        }
        .info {
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .date {
            color: #7f8c8d;
            font-size: 0.9em;
        }
    </style>
</head>
<body>
    <div class="info">
        <h1>Стартовая страница для ${full_hostname}</h1>
        <p>Виртуальный хост успешно создан</p>
        <p class="date">Создан: $(date '+%Y-%m-%d %H:%M:%S')</p>
    </div>
</body>
</html>
EOF

    chown apache:apache "$index_file" 2>/dev/null
    log_ok "index.html создан"
}

# ------------------------------------------------------------
# Включение хоста в Apache
# ------------------------------------------------------------

function enable_vhost() {
    local full_hostname="$1"
    local available="$VHOST_AVAILABLE/${full_hostname}.conf"
    local enabled="$VHOST_ENABLED/${full_hostname}.conf"

    log_info "Включение виртуального хоста"

    if [[ -L "$enabled" ]]; then
        log_warn "Симлинк уже существует: $enabled"
        return 0
    fi

    ln -s "$available" "$enabled"
    log_ok "Хост включён: $enabled"
}

# ------------------------------------------------------------
# Перезагрузка сервисов
# ------------------------------------------------------------

function reload_services() {
    log_info "Перезагрузка сервисов"

    # PHP-FPM
    if systemctl reload php-fpm 2>/dev/null; then
        log_ok "PHP-FPM перезагружен"
    else
        log_warn "Не удалось перезагрузить PHP-FPM через systemctl"
    fi

    # Apache
    if systemctl reload httpd 2>/dev/null; then
        log_ok "Apache перезагружен"
    else
        log_warn "Не удалось перезагрузить Apache, пробую apachectl"
        if apachectl graceful 2>/dev/null; then
            log_ok "Apache перезагружен (graceful)"
        else
            log_error "Не удалось перезагрузить Apache"
            return 1
        fi
    fi

    return 0
}

# ------------------------------------------------------------
# Создание MySQL пользователя и БД
# ------------------------------------------------------------

function create_mysql_user() {
    local db_name="$1"
    local db_user="$2"
    local db_pass="$3"

    log_info "Создание MySQL пользователя и БД"

    if [[ -z "$db_pass" ]]; then
        db_pass=$(openssl rand -base64 12 | tr -d '\n')
        log_info "Сгенерирован пароль: $db_pass"
    fi

    local sql="
CREATE DATABASE IF NOT EXISTS ${db_name}
    DEFAULT CHARACTER SET utf8
    COLLATE utf8_unicode_ci;

GRANT DELETE, INSERT, SELECT, UPDATE ON ${db_name}.*
    TO '${db_user}'@'localhost'
    IDENTIFIED BY '${db_pass}';

FLUSH PRIVILEGES;
"

    if mysql -u root -e "$sql" 2>/dev/null; then
        log_ok "База данных создана: $db_name"
        log_ok "Пользователь создан: $db_user@localhost"

        echo "$(date '+%Y-%m-%d %H:%M:%S') | DB: $db_name | User: $db_user | Pass: $db_pass" >> "$PASS_FILE"
        chmod 600 "$PASS_FILE"
        log_info "Креды сохранены в: $PASS_FILE"

        return 0
    else
        log_error "Ошибка создания MySQL пользователя/БД"
        return 1
    fi
}

# ------------------------------------------------------------
# Справка
# ------------------------------------------------------------

function show_help() {
    cat << EOF

${STAR_ICON} ${STAR_ICON} ${STAR_ICON} APACHE VIRTUAL HOST CREATOR ${STAR_ICON} ${STAR_ICON} ${STAR_ICON}

Назначение: Создание виртуального хоста Apache (HTTP/HTTPS) + PHP-FPM + MySQL

Использование:

    $(basename "$0") --host <hostname> [--db <db_name> --user <user>] [--pass <password>]

Параметры:

    --host HOSTNAME      Имя хоста (без домена)
    --db DB_NAME         Имя базы данных (опционально)
    --user USERNAME      Имя пользователя MySQL (опционально)
    --pass PASSWORD      Пароль (если не указан — сгенерируется)

    --domain DOMAIN      Домен (по умолчанию: $DOMAIN_SUFFIX)
    --php-version VER    Версия PHP (по умолчанию: автоопределение)

    -h, --help           Показать эту справку
    -v, --version        Показать версию

Что создаётся:

    1. Виртуальный хост (HTTP + HTTPS)
    2. PHP-FPM пул (с отдельным сокетом)
    3. Структура каталогов (public_html, log, sess, tmp)
    4. index.html
    5. MySQL БД и пользователь (если указаны)

Примеры:

    # Создать только хост
    $(basename "$0") --host site1

    # Создать хост + БД
    $(basename "$0") --host site2 --db site2_db --user site2_user

    # Создать хост + БД с паролем
    $(basename "$0") --host site3 --db site3_db --user site3_user --pass MyP@ss

EOF
}

# ------------------------------------------------------------
# Версия
# ------------------------------------------------------------

function show_version() {
    echo "Apache Virtual Host + MySQL User Creator"
    echo "Версия $VERSION"
    echo "© SSERGEY  Дата: 19.09.2015 (обновлено: 2026)"
}

# ------------------------------------------------------------
# Основная логика
# ------------------------------------------------------------

while [[ $# -gt 0 ]]; do
    case "$1" in
        --host)
            HOSTNAME="$2"
            shift 2
            ;;
        --db)
            DB_NAME="$2"
            shift 2
            ;;
        --user)
            DB_USER="$2"
            shift 2
            ;;
        --pass)
            DB_PASS="$2"
            shift 2
            ;;
        --domain)
            DOMAIN_SUFFIX="$2"
            shift 2
            ;;
        --php-version)
            PHP_VERSION="$2"
            shift 2
            ;;
        -h|--help)
            show_help
            log_session_end "HELP"
            exit 0
            ;;
        -v|--version)
            show_version
            log_session_end "VERSION"
            exit 0
            ;;
        *)
            log_error "Неизвестный параметр: $1"
            show_help
            STATUS="FAILED"
            exit 1
            ;;
    esac
done

# ------------------------------------------------------------
# Проверка прав
# ------------------------------------------------------------

if ! check_permissions; then
    STATUS="FAILED"
    exit 1
fi

# ------------------------------------------------------------
# Проверка зависимостей
# ------------------------------------------------------------

check_dependencies

# ------------------------------------------------------------
# Определение PHP версии
# ------------------------------------------------------------

if [[ -z "$HOSTNAME" ]]; then
    log_error "Не указан хост"
    show_help
    STATUS="FAILED"
    exit 1
fi

detect_php_version
log_info "Используется PHP версия: $PHP_VERSION"

# ------------------------------------------------------------
# Создание виртуального хоста
# ------------------------------------------------------------

echo
log_info "=== Создание виртуального хоста ==="

FULL_HOSTNAME=$(create_vhost_config "$HOSTNAME")
if [[ $? -ne 0 ]]; then
    STATUS="FAILED"
    exit 1
fi

create_directory_structure "$FULL_HOSTNAME"
create_index_html "$FULL_HOSTNAME"
create_php_fpm_pool "$FULL_HOSTNAME"
enable_vhost "$FULL_HOSTNAME"

# ------------------------------------------------------------
# Создание MySQL (если указано)
# ------------------------------------------------------------

if [[ -n "$DB_NAME" ]] && [[ -n "$DB_USER" ]]; then
    echo
    log_info "=== Создание MySQL пользователя ==="

    if create_mysql_user "$DB_NAME" "$DB_USER" "$DB_PASS"; then
        log_ok "MySQL пользователь и БД созданы"
    else
        STATUS="FAILED"
        exit 1
    fi
fi

# ------------------------------------------------------------
# Перезагрузка сервисов
# ------------------------------------------------------------

echo
if ! reload_services; then
    log_warn "Проверьте конфиги вручную"
fi

# ------------------------------------------------------------
# Итог
# ------------------------------------------------------------

echo
echo "${STAR_ICON} ${STAR_ICON} ${STAR_ICON} ИТОГ ${STAR_ICON} ${STAR_ICON} ${STAR_ICON}"
echo "  ${OK_ICON} Хост: ${FULL_HOSTNAME}"
echo "  ${INFO_ICON} Каталог: ${WEBROOT}/${FULL_HOSTNAME}"
echo "  ${INFO_ICON} Конфиг: ${VHOST_AVAILABLE}/${FULL_HOSTNAME}.conf"
echo "  ${INFO_ICON} PHP-FPM: /etc/php-fpm.d/${FULL_HOSTNAME}.conf"

if [[ -n "$DB_NAME" ]] && [[ -n "$DB_USER" ]]; then
    echo "  ${OK_ICON} БД: $DB_NAME"
    echo "  ${OK_ICON} Пользователь: $DB_USER@localhost"
    echo "  ${INFO_ICON} Креды: $PASS_FILE"
fi

echo
log_ok "Виртуальный хост создан: ${FULL_HOSTNAME}"

exit 0


Примеры использования:
Код: выделить все
# Создать только хост
sudo apache-add-vh.sh --host site1

# Создать хост + БД
sudo apache-add-vh.sh --host site2 --db site2_db --user site2_user

# Создать хост + БД с указанием пароля
sudo apache-add-vh.sh --host site3 --db site3_db --user site3_user --pass MyStr0ngP@ss

# Создать только БД
sudo apache-add-vh.sh --db new_db --user new_user

# Использовать другой домен
sudo apache-add-vh.sh --host site --domain example.com



Структура после создания:
Код: выделить все
/var/www/
└── site1.free-adm.ru/
    ├── public_html/
    │   └── index.html
    ├── log/
    │   ├── error.log
    │   ├── requests.log
    │   └── php.log
    ├── sess/
    ├── tmp/
    └──

/etc/httpd/sites-available/
└── site1.free-adm.ru.conf

/etc/httpd/sites-enabled/
└── site1.free-adm.ru.conf -> ../sites-available/site1.free-adm.ru.conf

/root/.mysql_creds.txt
└── 2026-09-03 14:30:00 | DB: site1_db | User: site1_user | Pass: xYz123


Что улучшено:
  • Объединение двух скриптов — один инструмент для хостов и БД
  • Единый стиль — цвета, логи, иконки
  • Гибкие параметры — --host, --db, --user, --pass
  • Автогенерация пароля — если не указан
  • Безопасное хранение кредов в /root/.mysql_creds.txt
  • Проверка зависимостей — Apache, MySQL/MariaDB
  • Автоопределение MySQL или MariaDB
  • Бэкап существующих конфигов перед перезаписью
  • Подтверждение перед перезаписью
Последний раз редактировалось root 04 сен 2026, 02:49, всего редактировалось 4 раз(а).
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 09 апр 2022, 19:35



 Включение по сети (Wake-on-LAN) 
Скрипт написан под стандартный дистрибутив Fedora, но адаптирован для использования на роутере Netgear WNDR3800 с прошивкой dd-wrt. Для полноценной работы скрипта нужен пакет arping из ревозитория rpmsphere
cat wol.sh
Код: выделить все
#!/bin/sh
##############################################
# Скрипт включения машин по сети
# перечисленных в файле vol.txt
# Составлено: SSERGEY
# Дата: 18.12.2019 v2.0
#############################################
ME=`basename $0`
BASE_PATH="$(dirname $0)"
vol="$BASE_PATH/wol.txt"
BRCST="195.0.1.255"
WOL="/usr/sbin/wol"

function start() {
    MAC=`grep $node $vol | awk -F" " '{ print $2 }'`
    echo "Пакет на включение машины $node отправлен"
    $WOL -i $BRCST -p 9 $MAC
}

function create() {
    if grep -q $node $vol;
    then
        echo "Указанное имя $node уже существует"
    else
        MAC=`arping -c 1 -I enp5s0 $node | grep "reply" | awk '{print $5}' | cut -c 2-18`
        echo "$node $MAC" >> $vol
    fi
}

function help() {
    echo -e "\nНазначение: Скрипт включения машин по сети"
    echo -e "\nИспользовать:"
    echo -e "\t\t$ME -s | --start hostname"
    echo -e "\t\t$ME -c | --create hostname"
    echo -e "\t\t$ME -h | --help | -v | --ver"
    echo -e "\nПараметры запуска"
    echo -e "\t\t-s | --start\t-\tВключить машину с указанным именем"
    echo -e "\t\t-c | --create\t-\tСоздать запись о машине на основе DNS-имени"
    echo -e "\t\t-h | --help\t\t-\tПоказать помощь"
    echo -e "\t\t-v | --ver\t\t-\tВыводит версию "
}

function ver() {
    echo -e "\n\t$ME Версия 2.0\t©SSERGEY\tДата: 18.12.2019"
}

if [ $# -eq 0 ]
then
    echo "ОШИБКА: Запуск без параметров не возможен"
    help
    exit 1
else
    for arg in "$@"
    do
        case $arg in
            "-s" | "--start")
            node="$2"
            start
            exit;;

            "-c" | "--create")
                node="$2"
                create
                exit;;

            "-h" | "--help")
                help
                exit;;

            "-v" | "--ver")
                ver
                exit;;

            *)  echo "ОШИБКА: Недопустимый параметр"
                help
                exit 1 ;;
        esac
    done
fi
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 09 апр 2022, 19:36



 Построение файлов зон для DNS-сервера 
cat create-zone.sh
Код: выделить все
#!/bin/bash
##############################################
# создание зонных файлов для DNS-сервера
# Составлено: SSERGEY
# Дата: 13.01.2017 v1.0
#############################################
#ZONEROOT="/var/named/master/"
ZONEROOT="/root/"
HOSTNAME=$1
ZONE=$HOSTNAME | awk -F. '{print $2"."$3}'
HOST=$HOSTNAME | awk -F. '{print $1}'
ZONE_IP=$2 | awk -F. '{print $3"."$2"."$1}'
SN=`date "+%Y%m%d"`."00"
IP=$2
echo "$HOST $ZONE"
function CreateZone(){
cat <<EOF > ${ZONEROOT}${ZONE}.zone
\$TTL 900
\$ORIGIN ${ZONE}.
@     SOA host.${ZONE}. root.${ZONE}. (
                  $SN   ; serial
                  900          ; 15 Minutes slave refresh interval
                  600          ; 10 Minutes slave retry interval
                  2592000      ; 1 month slave copy expire time
                  900          ; 15 Minutes NXDOMAIN cache time
                  )

          NS    host.${ZONE}.
          ;; add Slave server
          ;; IN  NS      ns.example.host.
          MX 10 host.${ZONE}.

@         A     ${IP}
host      A     ${IP}
EOF
}

function CreateZoneRev(){
cat <<EOF > ${ZONEROOT}${ZONE_IP}.zone
\$TTL 30m
\$ORIGIN ${ZONE_IP}.in-addr.arpa.
@       SOA host.${ZONE}. root.${ZONE}. (
                  2016082101
                      10h; slave-server connection preiod
                      1h; retry
                      1w; lifetime
                      1m; negative ttl
                      )

      NS host.${ZONE}.

15    PTR host.${ZONE}.
EOF
}

if [ $ZONE ! "" ]
then
    if [ ! -f "${ZONEROOT}${ZONE}.zone" ];
        then
        CreateZone
        echo "Создана новая зона прямого просмотра ${ZONE}"
    else
       echo "зона ${ZONE} уже существует"
    fi

        if [ ! -f "${ZONEROOT}${ZONE_IP}.zone" ];
        then
                CreateZoneRev
                echo "Создана новая зона обратного просмотра ${ZONE_IP}.in-addr.arpa."
        else
                echo "зона обратного просмотра ${ZONE_IP} уже существует"
                fi

elif [ "$1" = 'help' ] || [ "$1" = '' ] || [ "$2" = '' ];
then
    echo "Использование: Для создания domain.ru просто запустите команду"
    echo "'${0} host.domain.ru 192.168.1.5'"
fi
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

#

Сообщение root » 09 апр 2022, 19:38



 Поиск дубликатов в указанном каталоге 
cat md5-dup-finder.sh
Код: выделить все
#!/bin/bash

# ============================================================
# MD5 Duplicate Finder - Professional Edition
# ============================================================

VERSION="2.0"

# ------------------------------------------------------------
# Настройки
# ------------------------------------------------------------

DEFAULT_ALGORITHM="md5"          # md5 | sha1 | sha256
DEFAULT_MIN_SIZE="0"              # Минимальный размер файла (байт)
DEFAULT_MAX_DEPTH=""              # Глубина поиска (пусто = без ограничений)
DEFAULT_IGNORE_PATTERNS=(
    "*/.*"                        # Скрытые папки
    "*/node_modules/*"            # Node.js зависимости
    "*/venv/*"                    # Python виртуальное окружение
    "*/__pycache__/*"             # Python кеш
    "*/.git/*"                    # Git репозитории
    "*/Trash/*"                   # Корзина
    "*/temp/*"                    # Временные файлы
    "*/tmp/*"
)

LOG_LEVEL=3
USE_SYSLOG=false

# ------------------------------------------------------------
# Unicode / ASCII
# ------------------------------------------------------------

if [[ "${1:-}" == "--no-icons" ]]; then
    INFO_ICON=">"
    OK_ICON="+"
    WARN_ICON="!"
    ERR_ICON="x"
    DEBUG_ICON="D"
    ARROW_ICON="->"
    STAR_ICON="*"
    SIZE_ICON="[S]"
else
    INFO_ICON=$'\u2192'
    OK_ICON=$'\u2713'
    WARN_ICON=$'\u26A0'
    ERR_ICON=$'\u2717'
    DEBUG_ICON=$'\u2022'
    ARROW_ICON=$'\u21B3'
    STAR_ICON=$'\u2605'
    SIZE_ICON=$'\U0001F4E6'
fi

# ------------------------------------------------------------
# Переменные
# ------------------------------------------------------------

STATUS="SUCCESS"
LOG_SESSION_ENDED=false
LOG_SESSION_STARTED=false

LOG_FILE="/tmp/md5-finder.log"
TEMP_DIR="/tmp/md5_finder_$$"

ALGORITHM="$DEFAULT_ALGORITHM"
MIN_SIZE="$DEFAULT_MIN_SIZE"
MAX_DEPTH="$DEFAULT_MAX_DEPTH"
DELETE_MODE=false
DRY_RUN=false
SHOW_SIZE=false
SHOW_PROGRESS=false
OUTPUT_FILE=""

# ------------------------------------------------------------
# Логирование
# ------------------------------------------------------------

function _log() {
    local level="$1"; shift
    local message="$*"
    local timestamp

    timestamp="$(date '+%Y-%m-%d %H:%M:%S')"

    local level_num level_tag color_tag color_reset

    case "$level" in
        ERROR) level_num=1; level_tag="${ERR_ICON} ERROR"; color_tag="\033[1;31m" ;;
        WARN)  level_num=2; level_tag="${WARN_ICON} WARN "; color_tag="\033[1;33m" ;;
        INFO)  level_num=3; level_tag="${INFO_ICON} INFO "; color_tag="\033[1;34m" ;;
        OK)    level_num=3; level_tag="${OK_ICON} OK   ";  color_tag="\033[1;32m" ;;
        DEBUG) level_num=4; level_tag="${DEBUG_ICON} DEBUG"; color_tag="\033[0;90m" ;;
        *)     level_num=3; level_tag="INFO"; color_tag="\033[0m" ;;
    esac

    color_reset="\033[0m"

    echo "[$timestamp] [$level_tag] $message" >> "$LOG_FILE"

    if (( level_num <= LOG_LEVEL )); then
        if [[ -t 1 ]]; then
            echo -e "${color_tag}[$timestamp] [$level_tag]${color_reset} $message"
        else
            echo "[$timestamp] [$level_tag] $message"
        fi
    fi
}

log_info()  { _log INFO  "$@"; }
log_warn()  { _log WARN  "$@"; }
log_error() { _log ERROR "$@"; }
log_ok()    { _log OK    "$@"; }
log_debug() { _log DEBUG "$@"; }

# ------------------------------------------------------------
# Session Log
# ------------------------------------------------------------

function log_session_start() {

    local line="START | MODE: MD5_FINDER_PRO | VERSION: $VERSION"
    local width=60
    local padding=$(( (width - ${#line}) / 2 ))

    printf '=%.0s' $(seq 1 $width)
    printf "\n%*s%s\n" "$padding" "" "$line"
    printf '=%.0s' $(seq 1 $width)
    echo
    echo

    LOG_SESSION_STARTED=true
}

function log_session_end() {

    local status="$1"

    local line="END | STATUS: $status"
    local width=60
    local padding=$(( (width - ${#line}) / 2 ))

    echo
    printf '=%.0s' $(seq 1 $width)
    echo
    printf "%*s%s\n" "$padding" "" "$line"
    printf '=%.0s' $(seq 1 $width)
    echo

    LOG_SESSION_ENDED=true
}

# ------------------------------------------------------------
# Cleanup
# ------------------------------------------------------------

cleanup() {

    log_debug "Очистка временных файлов..."
    rm -rf "$TEMP_DIR"

    if [[ "$LOG_SESSION_ENDED" == false ]]; then
        log_session_end "$STATUS"
    fi
}

trap cleanup EXIT
trap 'STATUS="FAILED"; exit 1' INT TERM

mkdir -p "$TEMP_DIR"

# ------------------------------------------------------------
# Header
# ------------------------------------------------------------

log_session_start

log_info "Скрипт: $(basename "$0")"
log_info "Версия: $VERSION"

# ------------------------------------------------------------
# Проверка зависимостей
# ------------------------------------------------------------

function check_dependencies() {
    local deps=("find" "xargs" "sort" "awk" "grep" "sed" "du" "realpath")

    # Добавляем выбранный алгоритм
    deps+=("${ALGORITHM}sum")

    local missing=()

    for dep in "${deps[@]}"; do
        if ! command -v "$dep" &>/dev/null; then
            missing+=("$dep")
        fi
    done

    if [[ ${#missing[@]} -gt 0 ]]; then
        log_error "Отсутствуют зависимости: ${missing[*]}"
        return 1
    fi

    log_ok "Все зависимости установлены"
    return 0
}

# ------------------------------------------------------------
# Функция построения игнор-паттернов
# ------------------------------------------------------------

function build_ignore_patterns() {
    local patterns=()

    # Добавляем системные паттерны
    for pattern in "${DEFAULT_IGNORE_PATTERNS[@]}"; do
        patterns+=("-not" "-path" "$pattern")
    done

    # Добавляем пользовательские
    if [[ -n "$CUSTOM_IGNORE_PATTERNS" ]]; then
        IFS=',' read -ra user_patterns <<< "$CUSTOM_IGNORE_PATTERNS"
        for pattern in "${user_patterns[@]}"; do
            patterns+=("-not" "-path" "$pattern")
        done
    fi

    echo "${patterns[@]}"
}

# ------------------------------------------------------------
# Функция форматирования размера
# ------------------------------------------------------------

function format_size() {
    local size="$1"

    if [[ "$size" -gt 1073741824 ]]; then
        echo "$(echo "scale=2; $size/1073741824" | bc) GB"
    elif [[ "$size" -gt 1048576 ]]; then
        echo "$(echo "scale=2; $size/1048576" | bc) MB"
    elif [[ "$size" -gt 1024 ]]; then
        echo "$(echo "scale=2; $size/1024" | bc) KB"
    else
        echo "${size} B"
    fi
}

# ------------------------------------------------------------
# Функция подсчёта файлов
# ------------------------------------------------------------

function count_files() {
    local dirpath="$1"
    local count=0

    if [[ -d "$dirpath" ]]; then
        count=$(find "$dirpath" -type f 2>/dev/null | wc -l)
    fi

    echo "$count"
}

# ------------------------------------------------------------
# Основная функция поиска дубликатов
# ------------------------------------------------------------

function find_duplicates() {
    local dirpath="$1"
    local hash_file="$TEMP_DIR/hash.sum"
    local sort_file="$TEMP_DIR/hash.sort"
    local temp_file="$TEMP_DIR/temp.sort"
    local final_file="$OUTPUT_FILE"

    log_info "Поиск дубликатов в: $dirpath"

    # Проверка существования каталога
    if [[ ! -d "$dirpath" ]]; then
        log_error "Каталог не существует: $dirpath"
        return 1
    fi

    # Получение абсолютного пути
    dirpath=$(realpath "$dirpath")
    log_info "Абсолютный путь: $dirpath"

    # Подсчёт файлов
    local total_files=$(count_files "$dirpath")
    log_info "Всего файлов: $total_files"

    if [[ "$total_files" -eq 0 ]]; then
        log_warn "Каталог пуст: $dirpath"
        return 0
    fi

    # Сбор хэшей
    log_info "Сбор ${ALGORITHM^^} сумм файлов..."

    local find_cmd="find \"$dirpath\" -type f"

    # Добавляем ограничение по глубине
    if [[ -n "$MAX_DEPTH" ]]; then
        find_cmd="$find_cmd -maxdepth $MAX_DEPTH"
    fi

    # Добавляем игнор-паттерны
    local ignore_patterns=$(build_ignore_patterns)
    find_cmd="$find_cmd $ignore_patterns"

    # Добавляем фильтр по размеру
    if [[ "$MIN_SIZE" -gt 0 ]]; then
        find_cmd="$find_cmd -size +${MIN_SIZE}c"
    fi

    # Запускаем сбор
    if [[ "$SHOW_PROGRESS" == true ]]; then
        log_info "Сбор хэшей... (это может занять время)"
    fi

    if eval "$find_cmd -print0 2>/dev/null" | xargs -0 "${ALGORITHM}sum" > "$hash_file" 2>/dev/null; then
        local hashed_count=$(wc -l < "$hash_file")
        log_ok "Собрано хэшей: $hashed_count"

        if [[ "$hashed_count" -eq 0 ]]; then
            log_warn "Нет файлов для обработки"
            return 0
        fi
    else
        log_error "Ошибка при сборе ${ALGORITHM^^} сумм"
        return 1
    fi

    # Сортировка по хэшу
    log_info "Сортировка хэшей..."
    sort -k1 "$hash_file" > "$sort_file"
    log_ok "Сортировка завершена"

    # Поиск дубликатов
    log_info "Поиск дубликатов..."
    cp "$sort_file" "$temp_file"

    local total_duplicates=0
    local total_size=0
    local current_hash=""
    local count=0
    local first_file=""

    # Читаем отсортированный файл и группируем
    while IFS= read -r line; do
        local hash=$(echo "$line" | awk '{print $1}')
        local file=$(echo "$line" | awk '{$1=""; print substr($0,2)}')

        if [[ "$hash" != "$current_hash" ]]; then
            # Новая группа
            if [[ "$count" -gt 1 ]]; then
                # Это дубликаты
                ((total_duplicates += count - 1))
                # Добавляем размер первого файла
                if [[ -f "$first_file" ]]; then
                    local size=$(stat -c%s "$first_file" 2>/dev/null)
                    ((total_size += size * (count - 1)))
                fi
            fi
            current_hash="$hash"
            count=1
            first_file="$file"
        else
            ((count++))
            # Помечаем как дубликат
            echo "$line" >> "$temp_file.dups"
        fi
    done < "$sort_file"

    # Проверяем последнюю группу
    if [[ "$count" -gt 1 ]]; then
        ((total_duplicates += count - 1))
        if [[ -f "$first_file" ]]; then
            local size=$(stat -c%s "$first_file" 2>/dev/null)
            ((total_size += size * (count - 1)))
        fi
    fi

    # Формируем финальный файл
    if [[ -f "$temp_file.dups" ]]; then
        sort -k1 "$temp_file.dups" > "$final_file"
        rm -f "$temp_file.dups"
    fi

    # Проверка результата
    if [[ -f "$final_file" ]] && [[ -s "$final_file" ]]; then
        local dup_count=$(wc -l < "$final_file")
        log_ok "Найдено дубликатов: $dup_count файлов"
        log_ok "Всего дублируемого размера: $(format_size $total_size)"

        # Сохраняем информацию о размере
        echo "# Всего дубликатов: $dup_count" >> "$final_file"
        echo "# Общий размер: $(format_size $total_size)" >> "$final_file"
        echo "# Дата сканирования: $(date '+%Y-%m-%d %H:%M:%S')" >> "$final_file"
        echo "# Алгоритм: $ALGORITHM" >> "$final_file"
        echo "# Каталог: $dirpath" >> "$final_file"
        echo "---" >> "$final_file"

        if [[ "$SHOW_SIZE" == true ]]; then
            log_info "Сортировка по размеру..."
            sort -k2 -n "$final_file" -o "$final_file" 2>/dev/null
        fi

        log_info "Результат сохранён в: $final_file"

        # Показываем статистику
        echo
        echo "${STAR_ICON} Статистика:"
        echo "  ${INFO_ICON} Всего файлов: $total_files"
        echo "  ${OK_ICON} Найдено дубликатов: $dup_count"
        echo "  ${SIZE_ICON} Занимают места: $(format_size $total_size)"
        echo
    else
        log_info "Дубликатов не найдено"
        rm -f "$final_file" 2>/dev/null
        return 0
    fi

    return 0
}

# ------------------------------------------------------------
# Функция удаления дубликатов
# ------------------------------------------------------------

function delete_duplicates() {
    local sort_file="$1"
    local total=0
    local deleted=0
    local total_size=0

    log_info "Удаление дубликатов..."

    # Проверка наличия файла
    if [[ ! -f "$sort_file" ]]; then
        log_error "Файл не найден: $sort_file"
        log_info "Сначала запустите: $(basename "$0") -p /путь/к/каталогу"
        return 1
    fi

    # Проверка на пустой файл
    if [[ ! -s "$sort_file" ]]; then
        log_warn "Файл пуст: $sort_file"
        return 0
    fi

    # Игнорируем комментарии
    local real_count=$(grep -v '^#' "$sort_file" | grep -v '^---' | wc -l)
    total="$real_count"

    if [[ "$total" -eq 0 ]]; then
        log_warn "Нет записей для удаления"
        return 0
    fi

    # Подсчёт общего размера
    log_info "Подсчёт размера..."
    local total_size=0
    local count=0

    while IFS= read -r line; do
        # Пропускаем комментарии и заголовки
        [[ "$line" =~ ^#.*$ ]] && continue
        [[ "$line" == "---" ]] && continue
        [[ -z "$line" ]] && continue

        local file_path=$(echo "$line" | awk '{$1=""; print substr($0,2)}')
        if [[ -f "$file_path" ]]; then
            local size=$(stat -c%s "$file_path" 2>/dev/null)
            ((total_size += size))
            ((count++))
        fi
    done < "$sort_file"

    echo
    echo "${WARN_ICON} ${WARN_ICON} ${WARN_ICON} ВНИМАНИЕ:"
    echo "  ${INFO_ICON} Будет удалено: $total файлов"
    echo "  ${SIZE_ICON} Освободится: $(format_size $total_size)"

    # Dry run
    if [[ "$DRY_RUN" == true ]]; then
        echo
        log_info "Режим DRY RUN - никакие файлы не будут удалены"
        log_info "Список файлов для удаления:"

        local num=0
        while IFS= read -r line; do
            [[ "$line" =~ ^#.*$ ]] && continue
            [[ "$line" == "---" ]] && continue
            [[ -z "$line" ]] && continue

            local file_path=$(echo "$line" | awk '{$1=""; print substr($0,2)}')
            if [[ -f "$file_path" ]]; then
                ((num++))
                local size=$(stat -c%s "$file_path" 2>/dev/null)
                echo "  ${ARROW_ICON} [$num] $(basename "$file_path") ($(format_size $size))"
                echo "      ${DEBUG_ICON} $file_path"
            fi
        done < "$sort_file"

        echo
        log_info "Всего файлов для удаления: $num"
        return 0
    fi

    # Запрос подтверждения
    echo
    echo -n "${WARN_ICON} Продолжить удаление? (y/N): "
    read -r confirm

    if [[ "$confirm" != "y" ]] && [[ "$confirm" != "Y" ]]; then
        log_info "Операция отменена пользователем"
        return 0
    fi

    # Удаление файлов
    echo
    log_info "Начинаю удаление..."
    local num=0

    while IFS= read -r line; do
        [[ "$line" =~ ^#.*$ ]] && continue
        [[ "$line" == "---" ]] && continue
        [[ -z "$line" ]] && continue

        local file_path=$(echo "$line" | awk '{$1=""; print substr($0,2)}')

        if [[ -f "$file_path" ]]; then
            ((num++))
            local size=$(stat -c%s "$file_path" 2>/dev/null)

            if rm -f "$file_path" 2>/dev/null; then
                ((deleted++))
                log_debug "[$num/$total] Удалён: $(basename "$file_path") ($(format_size $size))"
            else
                log_warn "Не удалось удалить: $file_path"
            fi
        fi
    done < "$sort_file"

    echo
    log_ok "Удалено файлов: $deleted из $total"
    log_ok "Освобождено места: $(format_size $total_size)"

    # Сохраняем резервную копию списка
    local backup_file="${sort_file}.bak.$(date +%Y%m%d_%H%M%S)"
    cp "$sort_file" "$backup_file" 2>/dev/null
    log_info "Резервная копия сохранена: $backup_file"

    # Очищаем основной файл
    if [[ "$DELETE_MODE" == true ]]; then
        rm -f "$sort_file" 2>/dev/null
        log_info "Список удалён: $sort_file"
    fi

    return 0
}

# ------------------------------------------------------------
# Функция показа статистики
# ------------------------------------------------------------

function show_stats() {
    local sort_file="$1"

    if [[ ! -f "$sort_file" ]]; then
        log_error "Файл не найден: $sort_file"
        return 1
    fi

    local total_files=$(grep -v '^#' "$sort_file" | grep -v '^---' | wc -l)
    local total_size=0

    while IFS= read -r line; do
        [[ "$line" =~ ^#.*$ ]] && continue
        [[ "$line" == "---" ]] && continue
        [[ -z "$line" ]] && continue

        local file_path=$(echo "$line" | awk '{$1=""; print substr($0,2)}')
        if [[ -f "$file_path" ]]; then
            local size=$(stat -c%s "$file_path" 2>/dev/null)
            ((total_size += size))
        fi
    done < "$sort_file"

    echo
    echo "${STAR_ICON} Статистика дубликатов:"
    echo "  ${INFO_ICON} Файлов: $total_files"
    echo "  ${SIZE_ICON} Общий размер: $(format_size $total_size)"
    echo "  ${INFO_ICON} Файл: $(realpath "$sort_file")"
    echo
}

# ------------------------------------------------------------
# Справка
# ------------------------------------------------------------

function show_help() {
    cat << EOF

${STAR_ICON} ${STAR_ICON} ${STAR_ICON} MD5 DUPLICATE FINDER - PROFESSIONAL EDITION ${STAR_ICON} ${STAR_ICON} ${STAR_ICON}

Назначение: Поиск и удаление дубликатов файлов по хэш-суммам

Использование: $(basename "$0") -p ПУТЬ [ОПЦИИ]

Обязательные параметры:

    -p, --path ПУТЬ        Поиск дубликатов в указанном каталоге

Опции:

    -a, --algo АЛГОРИТМ    Алгоритм хэширования (md5|sha1|sha256)
                           По умолчанию: md5

    -o, --output ФАЙЛ      Сохранить результат в указанный файл
                           По умолчанию: ./duplicates.txt

    -d, --delete           Удалить найденные дубликаты
                           (требуется наличие файла с результатами)

    -n, --dry-run          Режим предпросмотра (не удалять файлы)

    -s, --show-size        Сортировка результатов по размеру файлов

    -m, --min-size БАЙТ    Минимальный размер файла для поиска
                           По умолчанию: 0

    -D, --max-depth ГЛУБ   Максимальная глубина поиска

    -i, --ignore ПАТТЕРН   Игнорировать паттерны (через запятую)
                           Пример: "*/temp/*,*.tmp"

    --stats                Показать статистику по файлу с дубликатами

    -v, --version          Показать версию скрипта

    -h, --help             Показать эту справку

Примеры:

    # Поиск дубликатов в каталоге
    $(basename "$0") -p /home/user/docs

    # Поиск с SHA256, сохранить в файл
    $(basename "$0") -p /home/user -a sha256 -o ./my_dups.txt

    # Предпросмотр удаления
    $(basename "$0") -d -n

    # Удаление дубликатов
    $(basename "$0") -d

    # Игнорировать временные файлы
    $(basename "$0") -p /home -i "*/tmp/*,*.tmp"

EOF
}

# ------------------------------------------------------------
# Версия
# ------------------------------------------------------------

function show_version() {
    echo "MD5 Duplicate Finder - Professional Edition"
    echo "Версия $VERSION"
    echo "© SSERGEY  Дата: 10.02.2017 (обновлено: 2026)"
}

# ------------------------------------------------------------
# Обработка ошибок
# ------------------------------------------------------------

function show_error() {
    log_error "Неверный или пустой параметр запуска"
    log_info "Для вызова справки запустите: $(basename "$0") -h"
}

# ------------------------------------------------------------
# Основная логика
# ------------------------------------------------------------

# Парсинг аргументов
ARGS=$(getopt -o "hp:a:o:dm:s:D:i:nv" --long "help,path:,algo:,output:,delete,min-size:,max-depth:,ignore:,stats,dry-run,show-size,version" -n "$(basename "$0")" -- "$@")

if [[ $? -ne 0 ]]; then
    show_error
    STATUS="FAILED"
    exit 1
fi

eval set -- "$ARGS"

while true; do
    case "$1" in
        -h|--help)
            show_help
            log_session_end "HELP"
            exit 0
            ;;
        -v|--version)
            show_version
            log_session_end "VERSION"
            exit 0
            ;;
        -p|--path)
            DIRPATH="$2"
            shift 2
            ;;
        -a|--algo)
            ALGORITHM="$2"
            shift 2
            ;;
        -o|--output)
            OUTPUT_FILE="$2"
            shift 2
            ;;
        -d|--delete)
            DELETE_MODE=true
            shift
            ;;
        -n|--dry-run)
            DRY_RUN=true
            shift
            ;;
        -s|--show-size)
            SHOW_SIZE=true
            shift
            ;;
        -m|--min-size)
            MIN_SIZE="$2"
            shift 2
            ;;
        -D|--max-depth)
            MAX_DEPTH="$2"
            shift 2
            ;;
        -i|--ignore)
            CUSTOM_IGNORE_PATTERNS="$2"
            shift 2
            ;;
        --stats)
            shift
            # Показываем статистику по дубликатам
            if [[ -f "./duplicates.txt" ]]; then
                show_stats "./duplicates.txt"
            elif [[ -f "$OUTPUT_FILE" ]]; then
                show_stats "$OUTPUT_FILE"
            else
                log_error "Файл с дубликатами не найден"
                STATUS="FAILED"
                exit 1
            fi
            log_session_end "STATS"
            exit 0
            ;;
        --)
            shift
            break
            ;;
        *)
            show_error
            STATUS="FAILED"
            exit 1
            ;;
    esac
done

# Проверка алгоритма
if [[ ! "$ALGORITHM" =~ ^(md5|sha1|sha256)$ ]]; then
    log_error "Неподдерживаемый алгоритм: $ALGORITHM"
    log_info "Доступные: md5, sha1, sha256"
    STATUS="FAILED"
    exit 1
fi

# Проверка прав
if [[ "$DELETE_MODE" == true ]] && [[ $EUID -ne 0 ]]; then
    log_warn "Для удаления файлов могут потребоваться права суперпользователя"
    if [[ "$DRY_RUN" == false ]]; then
        log_info "Попробуйте: sudo $(basename "$0") $*"
    fi
fi

# Проверка зависимостей
if ! check_dependencies; then
    STATUS="FAILED"
    exit 1
fi

# Установка выходного файла
if [[ -z "$OUTPUT_FILE" ]]; then
    OUTPUT_FILE="./duplicates.txt"
fi

# Основная логика
if [[ -n "$DIRPATH" ]]; then
    log_info "Каталог для поиска: $DIRPATH"
    log_info "Алгоритм: $ALGORITHM"
    log_info "Мин. размер: $MIN_SIZE байт"

    if find_duplicates "$DIRPATH"; then
        log_ok "Поиск дубликатов завершён"
    else
        STATUS="FAILED"
        exit 1
    fi
elif [[ "$DELETE_MODE" == true ]]; then
    # Проверка существования файла с дубликатами
    if [[ ! -f "$OUTPUT_FILE" ]]; then
        log_error "Файл с дубликатами не найден: $OUTPUT_FILE"
        log_info "Сначала запустите: $(basename "$0") -p /путь/к/каталогу"
        STATUS="FAILED"
        exit 1
    fi

    if delete_duplicates "$OUTPUT_FILE"; then
        log_ok "Удаление дубликатов завершено"
    else
        STATUS="FAILED"
        exit 1
    fi
else
    show_error
    STATUS="FAILED"
    exit 1
fi

# ------------------------------------------------------------
# Итог
# ------------------------------------------------------------

log_info "Скрипт: $(basename "$0")"
log_info "Каталог: ${DIRPATH:-не указан}"
log_info "Режим: $([ "$DELETE_MODE" == true ] && echo "УДАЛЕНИЕ" || echo "ПОИСК")"

exit 0
Последний раз редактировалось root 04 сен 2026, 12:08, всего редактировалось 1 раз.
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 09 апр 2022, 19:39



 Примеры монтирования CIFS 
cat mnt-cifs.sh
Код: выделить все
#!/bin/sh
# IPv4
#mount -t cifs //195.0.1.3/SEVEN -o username="ssergey",password="password" /mnt/sergey
# IPv6
#mount -t cifs //fec0:128::10:18:2:182/SEVEN -o username="ssergey",password="password" /mnt/sergey
mount -t cifs //fec0:128::10:18:2:182/SEVEN /mnt/sergey -o username="sergey",password="password"
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 09 апр 2022, 19:40



 Синхронизация локального репозитория для CentOS 
cat repo-updates.sh
Код: выделить все
#!/bin/sh
#######################################################
# Синхронизация локального репозитория для CentOS 7.2
# Составлено: SSERGEY
# Дата: 25.07.2016 v1.0
#######################################################
rsync="rsync -arvth --bwlimit=1024"
mirror="rsync://ftp.yandex.ru/centos"
verlist="7.2.1511"
archlist="x86_64"
baselist="os updates extras"
local=/var/www/repo.free-adm.ru/public_html/centos

for ver in $verlist
do
    for arch in $archlist
    do
           for base in $baselist
           do
                   remote=$mirror/$ver/$base/$arch/
                   $rsync $remote $local/$ver/$base/$arch/
           done
    done
done
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 09 апр 2022, 19:42



 Очистка и переиндексация баз данных Postgres 
cat service-db.sh
Код: выделить все
#!/bin/bash
##############################################
# Обслуживание баз Postgres перечисленных в файле
# Составлено: SSERGEY
# Дата: 01.01.2017 v1.0
#############################################
BASE_PATH="$(dirname $(readlink -f $0))"
file="$BASE_PATH/db.txt"

echo "Остановка сервера 1C"
echo "==========================================="
systemctl stop srv1cv83
echo "Очистка и переиндексация баз данных Postgres"
echo "==========================================="
while read line
do
        case $line in
                [a-zA-Z]* )
                        if `psql -Upostgres -lqt | cut -d \| -f 1 | grep -qw $line`
                        then
                                echo "Очистка базы данных $line"
                                vacuumdb -h localhost -U postgres --analyze --full --dbname=$line > /dev/null
                                echo "Переиндексация базы данных $line"
                                psql -h localhost -Upostgres --dbname=$line -c "REINDEX DATABASE \"$line\";" > /dev/null
                                echo "==========================================="
                        else
                                echo "База $line не существует"
                                echo "==========================================="
                        fi
                        ;;
        esac
done < $file

echo "Запуск сервера 1C"
echo "==========================================="
systemctl start srv1cv83
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 09 апр 2022, 19:44



 backup.sh скрипт для архивирования баз 
db.txt - Список баз для резервирования
Код: выделить все
#!/bin/bash
##############################################
# BACKUP баз Postgres перечисленных в файле
# Составлено: SSERGEY
# Дата: 09.01.2017 v3.0
#############################################
BASE_PATH="$(dirname $(readlink -f $0))"
file="$BASE_PATH/db.txt"
BACKUP_PATH="/1C_backup"
systemctl stop srv1cv83
if [ $? -eq 0 ]
then
        echo "==========================================="
        echo "Сервера 1C остановлен"
        echo "==========================================="
else
        echo "==========================================="
        echo "Не удалось остановить Сервера 1C"
    echo "==========================================="
        exit 1
fi

echo "$BACKUP_PATH - Каталог для архивных копий"
echo "==========================================="
while read line
do
        case $line in
                [a-zA-Z]* )
                        if `psql -Upostgres -lqt | cut -d \| -f 1 | grep -qw $line`
                        then
                                backup=`date +%d-%m-%Y.%H:%M`".$line"
                                pg_dump -h localhost -U postgres -Fc -Z9 -c -C -f $BACKUP_PATH/$backup $line
                                # -Fc - format custom Вывести копию в архивном формате, пригодном
                                #       для дальнейшего использования утилитой pg_restore
                                # -Z9 - Уровень сжатия данных MAX.
                                # -c  - clean Включить в выходной файл команды удаления (DROP) объектов базы данных
                                #       перед командами создания (CREATE) этих объектов. Если дополнительно не указать
                                #       флаг --if-exists, то при восстановлении в базу данных, где некоторые объекты
                                #       отсутствуют, попытка удаления несуществующего объекта будет приводить к ошибке,
                                #       которую можно игнорировать.
                                # -C  - create Сформировать в начале вывода команду для создания базы данных и затем
                                #       подключения к ней. В этом случае не важно, какая база указана в параметрах
                                #       подключения перед выполнением скрипта. Также, если указан ключ --clean, то скрипт
                                #       сначала удалит, а затем пересоздаст базу данных перед подключением к ней.
                                if [ $? -eq 0 ]
                                then
                                        echo "Создан файл $backup копия базы  $line"
                                        echo "==========================================="
                                else
                                        echo "Не удалось создать backup для базы $line"
                    echo "==========================================="
                                fi
                        else
                                echo "База данных $line не существует"
                                echo "==========================================="
                        fi
                        ;;
        esac
done < $file
systemctl start srv1cv83
if [ $? -eq 0 ]
then
        echo "Сервера 1C запущен"
        echo "==========================================="
else
        echo "Не удалось запустить Сервера 1C"
        echo "==========================================="
        exit 2
fi

Или почти готовый сервис
Код: выделить все
#!/bin/bash
##############################################
# Зачатки сервиса
# BACKUP баз Postgres перечисленных в файле
# Составлено: SSERGEY
# Дата: 09.01.2017 v3.0
#############################################
BASE_PATH="${0%/*}"
file="$BASE_PATH/db.txt"
BACKUP_PATH="/1C_backup"
LOG="/var/log/db_backup"
systemctl stop srv1cv83

if [ $? -eq 0 ]
then
        echo "$(date) Сервер 1C остановлен" >> $LOG
else
        echo "$(date) Не удалось остановить Сервер 1C" >> $LOG
        exit 1
fi

echo "$(date) Каталог для архивных копи - $BACKUP_PATH" >> $LOG

while read line
do
        case $line in
                [a-zA-Z]* )
                        if `psql -Upostgres -lqt | cut -d \| -f 1 | grep -qw $line`
                        then
                                backup=`date +%d-%m-%Y.%H:%M`".$line"
                                pg_dump -h localhost -U postgres -Fc -Z9 -c -C -f $BACKUP_PATH/$backup $line
                                # -Fc - format custom Вывести копию в архивном формате, пригодном
                                #       для дальнейшего использования утилитой pg_restore
                                # -Z9 - Уровень сжатия данных MAX.
                                # -c  - clean Включить в выходной файл команды удаления (DROP) объектов базы данных
                                #       перед командами создания (CREATE) этих объектов. Если дополнительно не указать
                                #       флаг --if-exists, то при восстановлении в базу данных, где некоторые объекты
                                #       отсутствуют, попытка удаления несуществующего объекта будет приводить к ошибке,
                                #       которую можно игнорировать.
                                # -C  - create Сформировать в начале вывода команду для создания базы данных и затем
                                #       подключения к ней. В этом случае не важно, какая база указана в параметрах
                                #       подключения перед выполнением скрипта. Также, если указан ключ --clean, то скрипт
                                #       сначала удалит, а затем пересоздаст базу данных перед подключением к ней.
                                if [ $? -eq 0 ]
                                then
                                        echo "$(date) Создан файл $backup копия базы $line" >> $LOG
                                else
                                        echo "$(date) Не удалось создать backup для базы $line" >> $LOG
                                fi
                        else
                                echo "$(date) База данных $line не существует" >> $LOG
                        fi
                        ;;
        esac
done < $file

systemctl start srv1cv83
if [ $? -eq 0 ]
then
        echo "$(date) Сервер 1C запущен" >> $LOG
else
        echo "$(date) Не удалось запустить Сервер 1C" >> $LOG
        exit 2
fi

в итоге получаем в каталоге ~/backup файлы по формату "дата.имя_базы"
Код: выделить все
07-09-2015.OLGA
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 09 апр 2022, 19:45



 Список активных хостов в сети 
Сформировать список активных хостов в сети можно так:
Код: выделить все
fping -Asg 195.0.1.0/24 -r2 | /bin/grep alive | cut -d ' ' -f1  >> fping.txt

Результат записывается в файл fping.txt в текущем каталоге. Для функционирования необходима утилита fping которая ставиться из одноимённого пакета
Код: выделить все
dnf install fping
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 09 апр 2022, 19:46



 Тестирование группы хостов на корректность записей в прямой и обратной DNS-зоне 
список участвующих файлов
Код: выделить все
arp-ping.sh        ipv4-list        ipv6-list        dns-test.sh

Основной скрипт dns-test.sh
Код: выделить все
#!/bin/bash
##############################################
# Тестирование группы хостов на корректность
# записей в прямой и обратной DNS-зоне
# Чтение хостовой части происходит из файлов
# ipv4-list и ipv6-list
# Составлено: SSERGEY Дата: 17.01.2023 v1.2
#############################################
ME=`basename $0`
# Хоствая часть IPv4-адреса читается из файла ipv4-list
readarray -t host4 < ipv4-list
# Хоствая часть IPv6-адреса читается из файла ipv6-list
readarray -t host6 < ipv6-list
# Сетвая часть IP-адресов
net4="195.0.1."
net6="2001:470:1f21:16b::"
dns_srv="@195.0.1.3"

FILES=(hosts A.log AAAA.log PTR.log PTR6.log)
for F in ${!host4[@]}; do
        if [[ -f ${FILES[F]} ]] && [[ -s ${FILES[F]} ]]; then
            :> ${FILES[F]}
        fi
done

function TESTIPv4() {
    for i in ${!host4[@]}; do
        # Наполняем массив ответами DNS сервера записей PTR
        PTRFULL[n++]=`dig $dns_srv -x ${net4}${host4[i]}`
    done

    for x in ${!PTRFULL[@]}; do
        # Выризаем из массива PTRFULL FQDN
        PTR=`echo ${PTRFULL[x]} | cut -d " " -f 5`
        # Проверяем существование записей A  в зоне по FQDN
        A[n++]=`dig $dns_srv ${PTR}`
        echo "$PTR" >> hosts
    done

    echo -e "\n\t\t================================="
    echo -e "\t\tТестирование записей A для IPv4"
    echo -e "\t\t=================================\n"
    for a in ${!A[@]};  do
        printf "%s\n" "${A[a]}"
        echo ${A[a]} >> A.log
    done

    echo -e "\n\t\t================================="
    echo -e "\t\tТестирование записей PTR для IPv4"
    echo -e "\t\t=================================\n"
    for y in ${!PTRFULL[@]};  do
        printf "%s\n" "${PTRFULL[y]}"
        echo ${PTRFULL[y]} >> PTR.log
    done
}

function TESTIPv6() {
    for i in ${!host6[@]}; do
        PTRFULL[n++]=`dig $dns_srv -x ${net6}${host6[i]}`
    done

    for x in ${!PTRFULL[@]}; do
        PTR=`echo ${PTRFULL[x]} | cut -d " " -f 5`
        AAAA[n++]=`dig $dns_srv AAAA ${PTR}`
        echo "$PTR" >> hosts
    done

    echo -e "\n\t\t================================="
    echo -e "\t\tТестирование записей AAAA для IPv6"
    echo -e "\t\t=================================\n"
    for a in ${!AAAA[@]};  do
        printf "%s\n" "${AAAA[a]}"
        echo ${AAAA[a]} >> AAAA.log
    done

    echo -e "\n\t\t================================="
    echo -e "\t\tТестирование записей PTR для IPv6"
    echo -e "\t\t=================================\n"
    for y in ${!PTRFULL[@]};  do
        printf "%s\n" "${PTRFULL[y]}"
        echo ${PTRFULL[y]} >> PTR6.log
    done
}

function help(){
    printf "\n\t\t\t\t\t\tСправка\n
\t$ME: Тестирование группы хостов на корректность
\t\t\t\t записей в прямой и обратной DNS-зоне

\n\tПараметры:
\t-4 - Тестирование IPv4 записей
\t-6 - Тестирование IPv6 записей
\t-h - Справка к программе
\t-v - выводит версию программы\n"
}

function version() {
    printf "\n\t$ME Версия 1.2
\t\t\t\tДата: 18.01.2023\n"
}

function err(){
    echo -e "\n\tОшибка: Неверный или пустой параметр запуска"
    echo -e "\n\tДля вызова справки запустите $ME -h\n"
}

if [ -z "$1" ]
then
    err
    exit 1
else
    while getopts "46hv" opt ;
    do
        case $opt in
            4) TESTIPv4 ;;
            6) TESTIPv6 ;;
            h) help ;;
            v) version ;;
            ''|*) err
                exit 1 ;;
        esac
    done
fi

дополнительный скрипт arp-ping.sh
Код: выделить все
#!/bin/bash
#-vx
##############################################
# Сканирование MAC-адресов по списку из файла
# Составлено: SSERGEY Дата: 19.12.2014 v1.0
#############################################
while read LINE; do
    LINE2=`echo ${LINE}|grep -E -o "(^[0-9]{1,3}[\.])([0-9]{1,3}[\.])([0-9]{1,3}[\.])([0-9]{1,3})"`
    if [ "$LINE" == "$LINE2" ]
    then
        arp=`arping -c1 ${LINE} |grep -P -o '((([0-9a-fA-F]{2})[ :-]){5}[0-9a-fA-F]{2})'`
        if [ $? = 0 ]
        then
            echo $arp $LINE
        fi
    fi
done < ip-list
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 09 апр 2022, 19:48



 Управление виртуальными машинами скриптами 
Скрипт управления виртуальными машинами решает следующие задачи:
  1. создание файла со списком всех машин что есть в VirtualBox (в каталоге со скриптом)
  2. Запуск виртуальных машин по списку из файла
  3. Завершение всех запущенных машин (затачивалось под завершение системы)
  4. Вывести список запущенных машин
  5. Все действия с виртуальными машинами производятся от имени пользователя под котором они находятся

cat /sbin/my-script/vb-mng.sh
Код: выделить все
#!/bin/bash
##############################################
# Скрипт управления виртуальными машинами VirtualBox
# перечисленных в файле vb.txt
# ПРИМЕЧАНИЕ: В именах машин крайне нежелательны.
# Составлено: SSERGEY
# Дата: 29.10.2017 v1.0
#############################################
ME=`basename $0`
BASE_PATH="$(dirname $(readlink -f $0))"
vb="$BASE_PATH/vb.txt"
user="sergey"
DATE=`date +%d-%m-%Y`
LOG="/var/log/vb-mng.log"
# Шаблон ID виртуальной машины для проверки прочитанного из файла значения
REGEX="^[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}"

# --type gui - используется стандартный графический интерфейс (по умолчанию)
# --type sdl - Для запуска виртуальной машины с использованием простого графического
#                               интерфейса без элементов управления в фоновом режиме
# --type headless - Для запуска виртуальной машины без GUI в фоновом режиме
type="sdl"
# Чтобы запустить виртуальную машину без GUI:
#  VBoxHeadless --startvm Crunchabang
function start() {
        echo "$(date) ### Запуск виртуальных машин VirtualBox ###" >> $LOG
        # читаем файл со списком виртуальных машин построчно
        while read line
                do
                        # Проверяем является ли строка закомментированной
                        if [[ $line =~ $REGEX ]];
                        then
                        case $line in
                                * )
                                        # Проверяем существование виртуальной машины с именем в VirtualBox
                                        su $user -c "vboxmanage list vms | grep $line > /dev/null"
                                        if [ $? -eq 0 ]
                                        then
                                                # Запускаем виртуальную машину и проверяем успешность запуска по коду ответа
                                                su $user -c "virtualbox --startvm \"$line\" --type $type &"
                                                # Для запуска без графики (возможно сгодиться для сервиса запуска)
                                                # su $user -c "VBoxHeadless -startvm \"$line\" &"
                                                if [ $? -eq 0 ];
                                                then
                                                        # Определяем Имя по ID виртуальной машины для занесения в LOG
                                                        name=`su sergey -c "vboxmanage list vms" | grep "$line" | awk -F\" '{print $2}'`
                                                        echo "$(date) Виртуальная машина $name стартовала" >> $LOG
                                                fi
                                        else
                                                # Если запуск прошёл неудачно то заносим об этом запись в LOG
                                                echo "$(date) Виртуальной машины с указанным именем  $line не существует" >> $LOG
                                        fi
                        ;;
                        esac
                        else
                                # Если строка закомментирована, то пропускаем итерацию цикла
                                continue
                        fi

        done < $vb
}

function stop() {
        su $user -c "vboxmanage list runningvms | sed -r 's/.*\{(.*)\}/\1/' | xargs -L1 -I {} VBoxManage controlvm {} acpipowerbutton"
        if [ $? -eq 0 ];
    then
                echo "$(date) Завершение работы запущенных виртуальных машин"  >> $LOG
        else
                echo "$(date) Не удалось завершить работу виртуальных машин" >> $LOG

        fi
}

function create() {
        su $user -c "vboxmanage list vms | sed 's,[\"{}],,g;s/ /\n/g;s/^/##/'" > $vb
        echo -e "\n\tПроверить имена машин, в созданном файле $vb, на предмет переноса строки\n"
}

function show() {
        # Показать список запущенных машин
        su $user -c "vboxmanage list runningvms"
}

function help() {
        echo -e "\nНазначение: Скрипт управления виртуальными машинами VirtualBox"
        echo -e "\nИспользовать: $ME start | stop | show | create | -h | --help | -v | --ver\n"
        echo -e "\n\tПараметры запуска\n"
        echo -e "\t\tstart - Запустить виртуальные машины"
        echo -e "\t\tstop - Остановить запущенные виртуальные машины"
        echo -e "\t\tshow - Вывести список запущенных машин"
        echo -e "\t\tcreate - Создать файл с именами запущенных машин"
        echo -e "\t\t-h | --help - Показать помощь"
        echo -e "\t\t-v | --ver - выводит версию "
}

function ver() {
        echo "Версия 1.0"
        echo "© SSERGEY  Дата: 29.10.2017"
}

for arg in "$@"
do
    case $arg in
                "start" )                       start ;;
                "stop"  )                       stop ;;
                "show"  )           show ;;
                "create" )                      create ;;
                "-h" | "--help" )       help ;;
                "-v" | "--ver" )        ver  ;;
                *)                                      help
                                                        echo "ОШИБКА: Недопустимый параметр"
                                                        exit 1 ;;
        esac
done

Примерный вид файла со списком машин для их запуска
cat vb.txt
Код: выделить все
##TEST
2cdf77d5-0ff4-4a57-9499-fa38041bc74c

Теперь с помощью systemd создадим возможность выключать все запущенные машины. Для этого создадим сервис shutdown.service
cat /etc/systemd/system/shutdown.service
Код: выделить все
[Unit]
# Описание сервиса Действия при завершении системы
Description=System Shutdown Actions
# Отключить неявные зависимости
DefaultDependencies=no
# запускать данный юнит прежде чем указанные ниже.
Before=shutdown.target reboot.target halt.target

[Service]
# Тип сервиса - полезен для скриптов, которые выполняют одно задание и завершаются
Type=oneshot
# Запускаем исполняемый скрипт данного сервиса
ExecStart=/sbin/my-script/shutdown.sh
[Install]
# Содержит рекомендации по установке юнита. Описывает, в каких случаях юнит должен быть запущен.
# WantedBy - описывает, в каких случаях юнит должен быть активирован.
WantedBy=halt.target reboot.target shutdown.target

Этот сервис при завершении системы вызывает скрипт shutdown.sh в котором перечисляются действия при завершении системы
Теперь включаем сервис
Код: выделить все
systemctl enable shutdown.service

Либо можно обойтись без написания своего юнита, поместив нужные скрипты в
Код: выделить все
/usr/lib/systemd/system-shutdown

cat /sbin/my-script/shutdown.sh
Код: выделить все
#!/bin/bash
/sbin/my-script/vb-mng.sh stop
...

Запуск машин можно выполнить через автозапуск в любой графической оболочки
Код: выделить все
/sbin/my-script/vb-start.sh start

Либо написать сервис, подобный тому что изложен выше.
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 09 апр 2022, 19:50



 NMAP: Сканирование хостов и портов (обёртка) 
Код: выделить все
#!/bin/bash
#############################################
# Тестирование хостов на открытые порты
# Группа хостов проверяется на конкретный порт, а конкретный
# хост на доступность всего диапазона портов
# Составлено: SSERGEY  Дата: 16.11.2020 v1.1
#############################################
ME=`basename $0`

if [[ $1=="i" ]] || [[ $1=="t" ]]
then
    # Проверка переменных на корректность
    REGIP="^([0-9]{1,3}\.){3}[0-9]{1,3}$"
    if [[ $2=~$REGIP ]]
    then
        ip="$2"
    else
        echo "Введённое значедие не является IP адресом"
        exit
    fi
fi

if [[ $1=="s" ]]
then
    REGSUB="^([0-9]{1,3}\.){3}[0-9]{1,3}(/[0-9]{1,3})$"
    REGPORT="^([0-9]{1,2})$"
    if [[ $2=~"$REGSUB" ]]
    # && [[ $3=~$REGPORT ]]
    then
        subnet="$2"
        port="$3"
        echo "Введённое"
    else
        echo "Введённое значедие не является адресом подсети"
        exit
    fi
fi

function SUBNET() {
    nmap -p $port -sT $subnet -oG res
    cat res |grep open >result
}

function IP() {
    nmap -PE $ip -oN resultip
}

function OSSTYPE() {
    nmap -O --osscan-guess $ip
}

function help(){
    printf "\n\t\tСправка
\t$ME: Тестирование хостов на открытые порты
\n\t\tПараметры:
\t-s 192.168.1.0/24 80 - Сканировать хосты подсети для порта 80
\t-i 192.168.1.45  - Сканировать все порта на хосте
\t-t - Предположительная информация об установленной ОС на хосте
\t-v - Вывод версии $ME
\t-h - Вывод этой справки\n"
}

function version() {
    printf "\n\t$ME Версия 1.1 Дата: 16.11.2020\n"
}

function err(){
    echo -e "\n\tОшибка: Неверный или пустой параметр запуска"
    echo -e "\n\tДля вызова справки запустите $ME -h\n"
}

if [ -z "$1" ] && [-n "$1" ]; then
    err
    exit 1
else
    if [ $1="i" ]
    then
        while getopts "sithv" OPT ;
        do
        case ${OPT} in
            s)  SUBNET ;;
            i)  IP ;;
            t)  OSSTYPE ;;
            h)  help ;;
            v)  version ;;
            *)  err
                exit 1 ;;
        esac
            done
    fi
fi
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 09 апр 2022, 19:52



 Резервное копирование Файловой системы XFS 
Код: выделить все
#!/bin/bash
#-vx
#############################################
# Резервное копирование Файловой системы XFS
# Составлено: SSERGEY  Дата: 13.09.2019 v3.0
#############################################
ME=`basename $0`
DATE=`date '+%d-%m-%Y'`
# куда монитируется раздел для backup'ов
BACKUP="/mnt/BACKUP/$DATE"
declare -a EXT
EXT=(".*old" ".*OLD" ".*gz" ".*([0-9]{8})" ".*([0-9]{8}|old|OLD|gz)" ".*([a-z].[0-9])")
declare -a PATHLOG
PATHLOG=("/var/www/*/log" "/var/log" )
declare -A DEV
DEV=([boot]="/dev/nvme0n1p2" [root]="/dev/nvme0n1p3" [home]="/dev/nvme0n1p4" [var]="/dev/nvme0n1p5")
#######################################
function ClearLogs(){
    dnf clean all
    rm -f /var/cache/abrt-di/*
    rm -f /var/core/*
    # Очищаем старые логи
    for ((i=0; i<${#PATHLOG[@]}; i++)); do
        for ((x=0; x<${#EXT[@]}; x++)); do
            find ${PATHLOG[i]} -regextype posix-egrep -regex "${EXT[x]}$" -type f -print0 | xargs -0 rm -f
        done
    done
    unset PATHLOG EXT
    journalctl --rotate && journalctl --vacuum-time=1s -o short 2> /tmp/journ && tail -n1 /tmp/journ && rm -f /tmp/journ
    sync && echo 3 > /proc/sys/vm/drop_caches && sync
}
#######################################
function CreateBackup() {
    mkdir -p $BACKUP
    # Монтируем раздел для архивов Монтируем boot и root (/) в режиме RO
#   xfs_freeze -f / && xfs_freeze -f /boot && xfs_freeze -f /home && xfs_freeze -f /var
    if [ $? -eq 0 ]
    then
        for key in "${!DEV[@]}"; do
            xfsdump -l 0 -L "Backup level 0 of ${key} $DATE" -M "file" -f "$BACKUP/${key}.dump" ${DEV[$key]} > /dev/null 2>&1
            if [ $? -eq 0 ]
            then
                echo "ДАМП раздела ${key} (${DEV[$key]}) успешно создан"
            fi
        done
#   xfs_freeze -u / && xfs_freeze -u /boot && xfs_freeze -u /home && xfs_freeze -u /var
    else
        echo "Ошибка монтирования разделов"
    fi
}

function MakePart () {
    if [ ! -e "$DISK" ]; then
        printf "\n\tУказанный диск $DISK не существует"
        exit 1
    else
        printf "\n\tСоздание структуры разделов на $DISK"
        printf "\nТаблица разделов: gpt

            Модель: Seagate BarraCuda Q5 ZP500CV30001 (nvme)
            Диск /dev/nvme0n1: 476940MiB
            Таблица разделов: gpt
                 START       ENDE NAME                 Флаги
                 2048    411647   EFI System Partition загрузочный, esp
               411648   1460223   Boot
              1460224 211175423   RootFS
            211175424 840321023   HomesDir
            840321024 871778303   Var"

        # Структура разделов загрузочного диска
        # parted -a optimal -s $DISK 'mklabel msdos' \
        # 'mkpart primary fat32 2048s 411647s' 'set 1 efi on' 'name 1 "EFI System Partition"' \
        # 'mkpart primary xfs 411648s 1460223s'  'name 2 "Boot"' \
        # 'mkpart primary xfs 1460224s 211175423s' 'name 3 "RootFS"' \
        # 'mkpart primary xfs 211175424s 840321023s' 'name 4 "HomesDir"' \
        # 'mkpart primary xfs 840321024s 871778303s' 'name 5 "Var"'
    fi
}

function RecoveryDump () {
    printf "\n\tВосстановление файловой системы"
    echo $DISK"1"
    # xfsrestore -f /dev/st0 -L "Backup level 0 of boot" /mnt/boot/
    # xfsrestore -f /dev/st0 -L "Backup level 0 of root" /mnt/boot/
}

function help(){
    printf "\n\t\t\t\t\t\tСправка
\t$ME: Управление бэкапами файловой системы XFS
\n\t\t\t\t\t\tПараметры:
\t-b - Создать ДАМП файловой системы
\t-c - Создание структуры разделов на целевом диске
\t-r - Восстановление файловой системы из резервной копии
\t-v - Вывод версии $ME
\t-h - Вывод этой справки
\n\t\t\t\t\t\tИспользовать в SINGLE USER
\tЧтобы загрузить в монопольном режиме компьютер с загрузчиком GRUB, выполните
\tследующие действия:
\t1. Увидев окно приветствия GRUB при загрузке, нажмите любую клавишу для входа
\tв интерактивное меню GRUB.
\t2. Выберите Fedora с версией ядра, которую вы хотите загрузить, и нажмите \"e\"
\tдля редактирования параметров запуска ядра.   Перейдите к концу строки и введите
\tsingle или число \"1\" (номер уровня запуска системы) в качестве параметра
\t3. Нажмите CTRL+x или F10 для выхода из режима редактирования параметров ядра.
\tПосле выхода произойдёт запуск системы с откорректированными параметрами
\tИли можно перевести систему в режим восстановления выполнив команду:
\t\t\tsystemctl isolate rescue.target\n"
}

function version() {
    printf "\n\t$ME Версия 3.0 Дата: 10.03.2019\n"
}

function err(){
    echo -e "\n\tОшибка: Непверный или пустой параметр запуска"
    echo -e "\n\tДля вызова справки запустите $ME -h\n"
}

if [ -z "$1" ]
then
    err
    exit 1
else
    while getopts "bсrhv" opt ;
    do
        case $opt in
            b)  ClearLogs
                CreateBackup ;;
            с)  DISK="/dev/$2" ;
                MakePart ;;
            r)  DISK="/dev/$2" ;
                RecoveryDump ;;
            h) help ;;
            v) version ;;
            ''|*) err
                exit 1 ;;
        esac
    done
fi
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 09 апр 2022, 20:27



 Перезапуск сервисов после сна 
Создаём сам сервис, который запускается при выходе машины из сна. Данный сервис дёргает SH-скрипт из каталога /sbin
e /usr/lib/systemd/system/after-suspend.service
Код: выделить все
[Unit]
Description=After suspend
After=suspend.target

[Service]
User=root
Type=oneshot
ExecStart=/sbin/after-suspend.sh
TimeoutSec=30
StandardOutput=syslog

[Install]
WantedBy=suspend.target

Скрипт перезапуска сервисов. В него можно при необходимости добавить сервисы, нуждающиеся в перезапуске. Информация о результате перезапуска заносится в лог-файл
e /sbin/my-script/after-suspend.sh
Код: выделить все
#!/bin/bash
##############################################
# Перезапуск сервисов после сна
# Составлено: SSERGEY
# Дата: 04.04.2017 v1.0
#############################################
BASE_PATH="${0%/*}"
LOG="/var/log/after-suspend"
systemctl restart named > /dev/null 2>&1
if [ $? -eq 0 ]
then
        echo "$(date) Сервер DNS перезапущен" >> $LOG
else
        echo "$(date) Не удалось перезапустить Сервер DNS" >> $LOG
        exit 1
fi

Пример лог-файла
e /var/log/after-suspend
Код: выделить все
Вт апр  4 22:03:13 MSK 2017 Сервер DNS перезапущен
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 11 апр 2022, 21:58



 Динамическое сообщение дня (motd) 
скрипт использует утилиту lsb_release, которую можно получить, установив пакет redhat-lsb-core:
Код: выделить все
dnf install redhat-lsb-core

Создаём скрипт
Код: выделить все
e /sbin/my-script/dynmotd.sh

Наполняем его содержимым:
Код: выделить все
#!/bin/sh

##############################################
# Динамическое сообщение дня
# Составлено: SSERGEY
# Дата: 04.05.2022 v1.0
#############################################

FOR_CL='\033[0m'                        # RESET
FOR_BLACK='\033[01;30m'         # DARK GRAY
FOR_RED='\033[01;31m'           # LIGHT RED
FOR_GREEN='\033[01;32m'         # LIGHT GREEN
FOR_YELLOW='\033[01;33m'        # YELLOW
FOR_BLUE='\033[01;34m'          # LIGHT BLUE
FOR_MAGENTA='\033[01;35m'       # LIGHT PURPLE
FOR_CYAN='\033[01;36m'          # LIGHT CYAN
FOR_LGRAY='\033[00;37m'         # LIGHT GRAY
FOR_WHITE='\033[01;37m'         # WHITE
FOR_ORANGE="\033[38;5;209m"     # ORANGE

# Time of day
HOUR=$(date +"%H")
if [ $HOUR -lt 12  -a $HOUR -ge 0 ]; then TIME="morning"
elif [ $HOUR -lt 17 -a $HOUR -ge 12 ]; then TIME="afternoon"
else TIME="evening"
fi

# System uptime
uptime=`cat /proc/uptime | cut -f1 -d.`
upDays=$((uptime/60/60/24))
upHours=$((uptime/60/60%24))
upMins=$((uptime/60%60))

# System + Memory
F_SERVICE=`systemctl --failed | tail -n1 | cut -d " " -f1`
SYS_LOADS=`cat /proc/loadavg | awk '{print $1}'`
MEMORY_USED=`free -b | grep Mem | awk '{print $3/$2 * 100.0}'`
SWAP_USED=`free -b | grep Swap | awk '{print $3/$2 * 100.0}'`
NUM_PROCS=`ps aux | wc -l`
IPADDRESS=`hostname --all-ip-addresses`
RELEASE=`lsb_release -s -d | sed 's/"//g'`
HOST=`hostname -f`
KERNEL=`uname -a | awk '{print $1" "$3" "$12}'`
DATE=`date`
USERS=`users | wc -w`

[[ ${F_SERVICE} > 0 ]] && ST=${FOR_RED} || ST=${FOR_GREEN}

#
printf "${FOR_CYAN}================================================================\n"
printf "${FOR_LGRAY}    Good ${TIME}!                        ${FOR_ORANGE} IT Dept Free-Adm\n"
printf "${FOR_CYAN}================================================================\n"
printf "${FOR_LGRAY}  - Hostname         :${FOR_WHITE} ${HOST}\n"
printf "${FOR_LGRAY}  - Release          :${FOR_WHITE} ${RELEASE}\n"
printf "${FOR_LGRAY}  - Kernel           :${FOR_WHITE} ${KERNEL}\n"
printf "${FOR_LGRAY}  - Server Time      :${FOR_WHITE} %s %s %s %s %s %s\n" ${DATE}
printf "${FOR_LGRAY}  - IP Address       :${FOR_WHITE} %-13s %-13s\n" ${IPADDRESS}
printf "${FOR_LGRAY}  - Users            :${FOR_WHITE} Currently ${USERS} user(s) logged on\n"
printf "${FOR_LGRAY}  - System load      :${FOR_WHITE} ${SYS_LOADS} / ${NUM_PROCS} processes running\n"
printf "${FOR_LGRAY}  - Memory used      :${FOR_WHITE} %.2f %%\n"  ${MEMORY_USED}
printf "${FOR_LGRAY}  - Swap used        :${FOR_WHITE} %.2f %%\n" ${SWAP_USED}
printf "${FOR_LGRAY}  - System uptime    :${FOR_WHITE} %s days %s hours %s minutes\n" ${upDays}  $upHours ${upMins}
printf "${FOR_LGRAY}  - Services failed  :${ST} ${F_SERVICE}\n"
printf "${FOR_CYAN}================================================================\n${FOR_CL}"
#

Скрипты.
Внешний вид

Сделаем скрипт исполняемым:
Код: выделить все
chmod +x /sbin/my-script/dynmotd.sh

Отключим встроенную обработку motd для SSH-сессий:
Код: выделить все
nano /etc/ssh/sshd_config

Код: выделить все
...
PrintMotd no
...

Перезапустим службу:
Код: выделить все
systemctl restart sshd

Подключаем вызов скрипта в механизм обработки загрузки профиля пользователей, отредактировав основной системный конфигурационный файл profile
Код: выделить все
e /etc/profile

в конец файла /etc/profile добавляем вызов скрипта
Код: выделить все
...
# Dynamic motd
/usr/local/sbin/dynmotd.sh
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 29 июл 2024, 04:43



 Резервное копирование виртуальных машин VirtualBox 
Код: выделить все
#!/bin/bash
##############################################
# Скрипт архивирования виртуальными машинами VirtualBox
# # Составлено: SSERGEY
# Дата: 29.07.2024 v1.0
#############################################
# Конфигурационные параметры
ME=$(basename "$0")                       # Получаем имя запущенного скрипта
BASE_PATH="$(dirname "$(readlink -f "$0")")" # Получаем текущий каталог
BACKUP_DIR="/mnt/BACKUP/VIRTUALBOX"       # Директория для резервных копий
MAX_BACKUPS=5                             # Максимальное количество резервных копий
LOG_FILE="$BASE_PATH/vm_backup.log"       # Файл логирования
DATE_TIME=$(date +"%Y%m%d")               # Получаем текущую дату и время
BACKUP_PATH="$BACKUP_DIR/$DATE_TIME"

CREATE_DIR() {
# Проверяем, существует ли директория для резервных копий
if [ ! -d "$BACKUP_DIR" ]; then
    mkdir -p "$BACKUP_DIR"
fi

# Создаем каталог для резервных копий, если его еще нет
if [ ! -d "$BACKUP_PATH" ]; then
    mkdir -p "$BACKUP_PATH"
fi
}

# Функция для архивирования виртуальных машин
backup_vm() {
    local VM_NAME="$1"
    local OUTPUT_FILE="$BACKUP_PATH/$VM_NAME.ova"

    # Ваша команда для архивирования виртуальной машины, например:
    # vboxmanage export "$VM_NAME" --output "$OUTPUT_FILE"
    if vboxmanage export "$VM_NAME" --output "$OUTPUT_FILE"; then
        echo "$(date) - Архивирование VM '$VM_NAME' в '$OUTPUT_FILE'" >> "$LOG_FILE"
    else
        echo "$(date) - Ошибка при архивировании VM '$VM_NAME'" >> "$LOG_FILE"
    fi
}

CHECK_LIST() {
    local param="$1"
    if [ "$param" != "all" ]; then
        if vboxmanage list vms | grep -q "\"$param\""; then
            VM_LIST="$param"
        else
            echo "Ошибка: Виртуальная машина с именем '$param' отсутсвует."
            exit 1
        fi
    else
        VM_LIST=$(vboxmanage list vms | awk -F'"' '{print $2}')
    fi
    echo "$VM_LIST"
}

ARCH() {
    local VM_LIST="$1"
    CREATE_DIR

    for VM in $VM_LIST; do
        if  [ ! -f "$BACKUP_PATH/$VM.ova" ]; then
            backup_vm "$VM"
        else
            echo "Предупреждение: архив $BACKUP_PATH/$VM.ova уже существует."
            echo "$(date) - Предупреждение: архив $BACKUP_PATH/$VM.ova уже существует" >> "$LOG_FILE"
        fi

    done
}

HELP() {
    echo -e "\n\n\tСправка..."
    echo -e "\n\tНазначение: Скрипт архивирования виртуальных машин VirtualBox"
    echo -e "\t\t\t\tИмена машин НЕ должны содержать пробелов"
    echo -e "\t\t\t\tЗапускается из-под обычного пользователя"
    echo -e "\n\tИспользовать: $ME [all | name | show | help | ver]\n"
    echo -e "\n\tПараметры:\n"
    echo -e "\t\tall\t\t- Архивировать ВСЕ виртуальные машины\n"
    echo -e "\t\tname\t- Имя виртуальной машины для архивирования\n"
    echo -e "\t\tshow\t- Вывести список виртуальных машин\n"
    echo -e "\t\thelp\t- Показать помощь\n"
    echo -e "\t\tver\t\t- Вывести версию"
}

VER() {
    echo "©SSERGEY Дата: 29.07.2024 Версия 1.0"
}

DEL_OLD() {
    BACKUP_COUNT=$(ls -1 "$BACKUP_DIR" | wc -l)
    if [ "$BACKUP_COUNT" -gt "$MAX_BACKUPS" ]; then
        OLD_BACKUPS=$(ls -1t "$BACKUP_DIR" | tail -n +$((MAX_BACKUPS + 1)))
        for OLD_BACKUP in $OLD_BACKUPS; do
            rm -rf "$BACKUP_DIR/$OLD_BACKUP"
            echo "$(date) - Удален старый бэкап '$OLD_BACKUP'" >> "$LOG_FILE"
        done
    fi
}

# Проверяем, был ли передан параметр
if [ $# -eq 0 ]; then
    echo "Ошибка: Необходимо указать один параметр."
    echo "Для справки: $ME help"
    exit 1
fi

# Получаем первый параметр
param="$1"

# Проверяем значение параметра
case "$param" in
    help)
        HELP
        ;;
    show)
        echo "Список виртуальных машин..."
        vboxmanage list vms
        ;;
    ver)
        VER
        ;;
    all)
        VM_LIST=$(CHECK_LIST "$param")
        ARCH "$VM_LIST"
        DEL_OLD
        ;;
    *)
        VM_LIST=$(CHECK_LIST "$param")
        ARCH "$VM_LIST"
        DEL_OLD
        ;;
esac
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный

Сообщение root » 04 сен 2026, 02:19



 Переключение виртуальных сред VirtualBox и KVM 
Иногда приходится совмещать разные среды виртуализации на одном компьютере. Идея вообщем-то на грани добра и зла, но тем не менее при большом желании и такое возможно. Для облегчения загрузки / выгрузки сервисов и модулей ядра под конкретную среду виртуализации можно воспользоваться скриптом следующего вида:
vb-to-kvm.sh
Код: выделить все
#!/bin/bash
##############################################
# Скрипт переключения виртуальных сред  VirtualBox/KVM
# Составлено: SSERGEY
# Дата: 16.09.2025 v1.0
#############################################
ME=`basename $0`
BASE_PATH="$(dirname $(readlink -f $0))"

function KVM() {
    if [ "$1" = "kvm" ]; then
        modprobe -r vboxnetadp vboxnetflt vboxdrv || echo "Ошибка выгрузки модулей VirtualBox"
        modprobe kvm_amd kvm || echo "Ошибка загрузки модулей KVM"
        systemctl start libvirtd.socket
        systemctl start libvirtd.service
        echo "Переключился в режим KVM"
    fi
}

function VB() {
    if [ "$1" = "vb" ]; then
        systemctl stop libvirtd.service libvirtd.socket || echo "Ошибка остановки сервисов KVM"
        modprobe -r kvm_amd kvm  || echo "Ошибка выгрузки модулей KVM"
        modprobe vboxnetadp vboxnetflt vboxdrv || echo "Ошибка загрузки модулей VirtualBox"
        echo "Переключился в режим VirtualBox"
    fi
}

function HELP() {
    echo -e "\nНазначение: Скрипт переключения виртуальных сред VirtualBox / KVM"
    echo -e "\nИспользовать: $ME kvm | vb | -h | --help | -v | --ver\n"
    echo -e "\n\tПараметры запуска\n"
    echo -e "\t\tkvm - Переключился в режим  KVM"
    echo -e "\t\tvb - Переключился в режим VirtualBox"
    echo -e "\t\t-h | --help - Показать параметры запуска"
    echo -e "\t\t-v | --ver - выводит версию $ME"
}

function VER() {
    echo "Версия 1.0"
    echo "© SSERGEY  Дата: 16.09.2025"
}

for arg in "$@"
    do
    case $arg in
        "kvm")  KVM "$arg" ;;
        "vb" )  VB "$arg" ;;
        "-h" | "--help" )   HELP ;;
        "-v" | "--ver" )    VER  ;;
        *)                  HELP
                            echo "ОШИБКА: Недопустимый параметр"
                            exit 1 ;;
    esac
done


Последний раз поднималось root 04 сен 2026, 02:19.
Администрирование Fedora Linux + настройка сети и прочая IT-Ботва


Для желающих поддержать
Карта SB: 2202 2085 9514 5823


Лучше ужасный конец, чем ужас без конца!
Аватар пользователя
root
Администратор
 
Сообщений: 499
Зарегистрирован: 01 авг 2011, 09:36
Откуда: Моск. обл., г. Железнодорожный


Вернуться в Fedora

Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

cron