Proxmox LXC backup → Windows 11 с Bash

Ако работите с Proxmox сървъри и регулярно трябва да свалите бекъпи (backup) на LXC контейнери на локален компютър с Windows 11, вероятно знаете колко досадно може да бъде ръчното изпълнение на rsync команди за всеки нов бекъп файл. В тази статия ще споделя как създадох автоматизиран Bash скрипт, който решава този проблем елегантно и ефективно.
Проблемът
В моята работа често се налага да свалям бекъпи от Proxmox сървър, като използвам команди от типа:
rsync -avz --partial --progress -e ssh [email protected]:/backup512/dump/vzdump-lxc-109-2025_08_01-02_44_10.tar.zst /mnt/d/backup_proxmox
Проблемите с ръчния подход са очевидни:
- Трябва постоянно да проверявам за нови бекъпи
- Да помня кои файлове вече съм свалил
- Да сменям името на файла в командата за всеки нов бекъп
- Да управлявам локалното пространство, изтривайки стари бекъпи
Освен това, понякога се интересувам само от определени LXC контейнери (например 111 и 114), но тази нужда може да се промени с времето.
Решението
Създадох Bash скрипт, който автоматизира целия процес. Скриптът:
- Автоматично открива нови бекъпи на зададени LXC контейнери
- Помни кои файлове вече са свалени
- Сваля само новите бекъпи
- Автоматично изтрива стари локални бекъпи за спестяване на място
- Води подробни логове на дейността си
- Позволява лесна промяна на наблюдаваните контейнери
Необходими файлове
Решението се състои от два файла:
1. proxmox_backup_sync.sh – основният скрипт
Това е главният Bash скрипт, който извършва цялата работа. Съдържа функции за:
- Зареждане на конфигурация
- Откриване на нови отдалечени бекъпи
- Сваляне чрез rsync
- Проследяване на свалените файлове
- Изтриване на стари локални бекъпи
- Логване на дейностите
2. backup_config.conf – конфигурационен файл
Прост текстов файл с променливи, който определя:
- Данни за Proxmox сървъра (хост, потребител, пътища)
- Кои LXC контейнери да наблюдава
- Локални настройки (пътища, опции)
- Политика за запазване на стари бекъпи
Настройка и инсталация
Стъпка 1: Създаване на работна директория
mkdir ~/skript
cd ~/skript
Стъпка 2: Създаване на скрипта
Създайте файл proxmox_backup_sync.sh
и копирайте кода на скрипта в него.
#!/bin/bash
# Конфигурационен файл
CONFIG_FILE="$(dirname "$0")/backup_config.conf"
LOG_FILE="$(dirname "$0")/backup_sync.log"
DOWNLOADED_FILE="$(dirname "$0")/.downloaded_backups"
# Функция за логване
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Проверка дали конфигурационният файл съществува
if [[ ! -f "$CONFIG_FILE" ]]; then
log "ERROR: Конфигурационният файл $CONFIG_FILE не съществува!"
cat > "$CONFIG_FILE" << 'EOF'
# Конфигурация за Proxmox backup sync
PROXMOX_HOST=10.110.110.68
PROXMOX_USER=root
REMOTE_BACKUP_PATH=/backup512/dump
LOCAL_BACKUP_PATH=/mnt/d/backup_proxmox
# LXC контейнери за синхронизиране (разделени със запетая)
# Пример: LXC_IDS=109,111,114
LXC_IDS=111,114
# SSH опции (по избор)
SSH_OPTIONS="-o ConnectTimeout=30 -o ServerAliveInterval=60"
# Максимален брой дни за задържане на локални бекъпи (0 = безкрайно)
KEEP_DAYS=30
EOF
log "Създаден е примерен конфигурационен файл: $CONFIG_FILE"
log "Моля, редактирайте го според вашите нужди и стартирайте отново скрипта."
exit 1
fi
# Зареждане на конфигурацията
source "$CONFIG_FILE"
# Създаване на локална директория ако не съществува
mkdir -p "$LOCAL_BACKUP_PATH"
# Създаване на файл за проследяване на свалените бекъпи
touch "$DOWNLOADED_FILE"
log "Започвам проверка за нови бекъпи..."
log "Наблюдавани LXC контейнери: $LXC_IDS"
# Функция за получаване на списък с отдалечени бекъпи
get_remote_backups() {
local lxc_id=$1
ssh $SSH_OPTIONS "${PROXMOX_USER}@${PROXMOX_HOST}" \
"find ${REMOTE_BACKUP_PATH} -name 'vzdump-lxc-${lxc_id}-*.tar.zst' -type f -printf '%f\n'" 2>/dev/null
}
# Функция за проверка дали бекъп е вече свален
is_downloaded() {
local backup_name=$1
grep -Fxq "$backup_name" "$DOWNLOADED_FILE"
}
# Функция за маркиране на бекъп като свален
mark_as_downloaded() {
local backup_name=$1
echo "$backup_name" >> "$DOWNLOADED_FILE"
}
# Функция за изтриване на стари локални бекъпи
cleanup_old_backups() {
if [[ "$KEEP_DAYS" -gt 0 ]]; then
log "Изтривам локални бекъпи по-стари от $KEEP_DAYS дни..."
find "$LOCAL_BACKUP_PATH" -name "vzdump-lxc-*.tar.zst" -type f -mtime +$KEEP_DAYS -delete
fi
}
# Главен цикъл за всеки LXC контейнер
IFS=',' read -ra LXC_ARRAY <<< "$LXC_IDS"
for lxc_id in "${LXC_ARRAY[@]}"; do
lxc_id=$(echo "$lxc_id" | xargs) # Премахване на интервали
log "Проверявам за нови бекъпи на LXC $lxc_id..."
# Получаване на списък с отдалечени бекъпи
remote_backups=$(get_remote_backups "$lxc_id")
if [[ -z "$remote_backups" ]]; then
log "Няма намерени бекъпи за LXC $lxc_id"
continue
fi
# Проверка за всеки бекъп
while IFS= read -r backup_file; do
[[ -z "$backup_file" ]] && continue
if ! is_downloaded "$backup_file"; then
log "Намерен нов бекъп: $backup_file"
log "Започвам сваляне..."
# Изпълнение на rsync
if rsync -avz --partial --progress -e "ssh $SSH_OPTIONS" \
-e ssh "${PROXMOX_USER}@${PROXMOX_HOST}:${REMOTE_BACKUP_PATH}/${backup_file}" \
"${LOCAL_BACKUP_PATH}/"; then
log "Успешно свален: $backup_file"
mark_as_downloaded "$backup_file"
else
log "ERROR: Грешка при сваляне на $backup_file"
fi
else
log "Бекъп $backup_file вече е свален, прескачам..."
fi
done <<< "$remote_backups"
done
# Почистване на стари бекъпи
cleanup_old_backups
log "Завършена проверка за нови бекъпи."
Стъпка 3: Правомощия за изпълнение
chmod +x proxmox_backup_sync.sh
Стъпка 4: Първоначално стартиране
./proxmox_backup_sync.sh
При първото стартиране скриптът ще даде грешка и ще създаде примерен конфигурационен файл backup_config.conf
.
Стъпка 5: Редактиране на конфигурацията
Отворете backup_config.conf
и настройте според вашите нужди:
# Конфигурация за Proxmox backup sync
PROXMOX_HOST=10.110.110.68
PROXMOX_USER=root
REMOTE_BACKUP_PATH=/backup512/dump
LOCAL_BACKUP_PATH=/mnt/d/backup_proxmox
# LXC контейнери за синхронизиране (разделени със запетая)
LXC_IDS=111,114,117,120,
# SSH опции (по избор)
SSH_OPTIONS="-o ConnectTimeout=30 -o ServerAliveInterval=60"
# Максимален брой дни за задържане на локални бекъпи (0 = безкрайно)
KEEP_DAYS=7
Важни настройки:
PROXMOX_HOST
: IP адресът на вашия Proxmox сървърPROXMOX_USER
: SSH потребителско име (обикновено root)REMOTE_BACKUP_PATH
: Пътят до бекъпите на сървъраLOCAL_BACKUP_PATH
: Къде да се запазват локалните копияLXC_IDS
: Списък с ID-та на контейнерите (разделени със запетая)KEEP_DAYS
: След колко дни да се изтриват старите локални бекъпи
Стъпка 6: Тестово стартиране
./proxmox_backup_sync.sh
Сега скриптът трябва да работи и да започне да сваля новите бекъпи.
Как работи скриптът
Откриване на нови бекъпи
За всеки зададен в конфигурацията LXC контейнер, скриптът се свързва към Proxmox сървъра и търси файлове с шаблон vzdump-lxc-{ID}-*.tar.zst
.
Проследяване на свалените файлове
Скриптът поддържа скрит файл .downloaded_backups
, където записва имената на всички файлове, които вече е свалил. По този начин избягва повторното сваляне на същите бекъпи.
Сваляне
Използва се rsync с опции за възобновяване на прекъснати трансфери (--partial
) и показване на прогрес (--progress
).
Автоматично почистване
Според настройката KEEP_DAYS
, скриптът автоматично изтрива локалните бекъпи, които са по-стари от зададения период.
Логване
Всички дейности се записват в backup_sync.log
с времева отметка.
Автоматизация с Cron
За пълна автоматизация, можете да добавите скрипта в cron за периодично изпълнение:
# Редактиране на crontab
crontab -e
# Добавяне на ред за изпълнение на всеки 30 минути
*/30 * * * * /home/username/skript/proxmox_backup_sync.sh >> /home/username/skript/cron.log 2>&1
# Или веднъж дневно в 3:00 сутринта
0 3 * * * /home/username/skript/proxmox_backup_sync.sh >> /home/username/skript/cron.log 2>&1
Предимства на решението
Гъвкавост
Лесно можете да променяте кои LXC контейнери да наблюдавате, просто като редактирате LXC_IDS
в конфигурационния файл.
Надеждност
- Обработва мрежови грешки и timeouts
- Не сваля повторно същите файлове
- Възобновява прекъснати трансфери
Ефективност
- Използва минимални системни ресурси
- Оптимизирани rsync опции
- Автоматично управление на дисковото пространство
Проследимост
- Подробни логове на всички операции
- Лесно откриване на проблеми
- История на свалените бекъпи
Структура на файловете
След настройка, работната ви директория ще изглежда така:
~/skript/
├── proxmox_backup_sync.sh # Основният скрипт
├── backup_config.conf # Конфигурация
├── backup_sync.log # Логове (създава се автоматично)
├── .downloaded_backups # Проследяване на свалените файлове
└── cron.log # Логове от cron (ако използвате)
Заключение
Този скрипт значително опростява управлението на Proxmox бекъпи и спестява много време и усилия. Гъвкавата конфигурация позволява лесно адаптиране към различни нужди, а автоматичното управление на локалното пространство предотвратява проблеми с препълване на дисковете.
Скриптът е тестван в продукционна среда и се е доказал като надеждно решение за ежедневни backup операции. Препоръчвам го на всеки, който работи с Proxmox и се нуждае от автоматизация на backup процесите.
Съвети за използване:
- Започнете с малък
KEEP_DAYS
(3-7 дни) докато тествате - Проверете логовете редовно в началото
- При промяна на наблюдаваните контейнери, просто редактирайте конфигурацията
- За production използване, настройте cron за автоматично изпълнение
Надявам се този скрипт да ви бъде полезен и да спести от ежедневната ви работа с Proxmox бекъпи!
Създадох значително подобрена версия със следните нови функции:
🎯 Нови възможности:
1. Интерактивно меню
- Цветно, лесно за използване меню
- Опции за сваляне, качване, управление на контейнери и статистики
2. Управление на контейнери без редактиране на файлове
- Отделен файл
container_list.txt
за контейнерите - Добавяне/премахване на контейнери директно от менюто
- Показване на текущи контейнери
3. Функция за качване (upload)
- Качва локални бекъпи обратно на Proxmox сървъра
- Проверява дали файловете вече съществуват преди качване
- Използва същата rsync логика за ефективност
4. Подобрена функционалност
- Цветни съобщения за по-добра видимост
- Статистики – брой контейнери, свалени бекъпи, размер
- Командни аргументи за автоматизация (
-d
за download,-u
за upload) - По-добро логване и обработка на грешки
5. Файлова структура:
├── backup_sync.sh # Основният скрипт
├── backup_config.conf # Конфигурация
├── container_list.txt # Списък с контейнери
├── backup_sync.log # Лог файл
└── .downloaded_backups # Проследяване на свалени файлове
🚀 Как да използваш:
Интерактивно:
./backup_sync.sh
Автоматично (за cron):
./backup_sync.sh --download # Само сваляне
./backup_sync.sh --upload # Само качване
Добавяне на контейнери:
- Избери опция 3 от менюто
- Избери "Добави контейнер"
- Въведи ID-то на контейнера
Скриптът автоматично ще създаде всички необходими файлове при първо стартиране и ще ти даде възможност да управляваш контейнерите лесно, без да редактираш конфигурационни файлове всеки път!
Ето и самият скрипт:
#!/bin/bash
# Конфигурационен файл
CONFIG_FILE="$(dirname "$0")/backup_config.conf"
LOG_FILE="$(dirname "$0")/backup_sync.log"
DOWNLOADED_FILE="$(dirname "$0")/.downloaded_backups"
CONTAINER_LIST="$(dirname "$0")/container_list.txt"
# Цветове за по-добра визуализация
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Функция за логване
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Цветно съобщение
print_colored() {
local color=$1
local message=$2
echo -e "${color}${message}${NC}"
}
# Проверка дали конфигурационният файл съществува
check_config() {
if [[ ! -f "$CONFIG_FILE" ]]; then
log "ERROR: Конфигурационният файл $CONFIG_FILE не съществува!"
cat > "$CONFIG_FILE" << 'EOF'
# Конфигурация за Proxmox backup sync
PROXMOX_HOST=10.110.110.68
PROXMOX_USER=root
REMOTE_BACKUP_PATH=/backup512/dump
LOCAL_BACKUP_PATH=/mnt/d/backup_proxmox
# SSH опции
SSH_OPTIONS="-o ConnectTimeout=30 -o ServerAliveInterval=60"
# Максимален брой дни за задържане на локални бекъпи (0 = безкрайно)
KEEP_DAYS=30
EOF
log "Създаден е примерен конфигурационен файл: $CONFIG_FILE"
log "Моля, редактирайте го според вашите нужди."
return 1
fi
return 0
}
# Създаване на файл с контейнери ако не съществува
check_container_list() {
if [[ ! -f "$CONTAINER_LIST" ]]; then
print_colored $YELLOW "Файлът с контейнери не съществува. Създавам нов..."
echo "# Списък с LXC контейнери за синхронизиране" > "$CONTAINER_LIST"
echo "# Добавете по един ID на ред" >> "$CONTAINER_LIST"
echo "111" >> "$CONTAINER_LIST"
echo "114" >> "$CONTAINER_LIST"
print_colored $GREEN "Създаден файл: $CONTAINER_LIST"
print_colored $YELLOW "Моля, редактирайте го за да добавите вашите контейнери."
fi
}
# Зареждане на контейнерите от файл
load_containers() {
local containers=()
if [[ -f "$CONTAINER_LIST" ]]; then
while IFS= read -r line; do
# Игнориране на коментари и празни редове
[[ "$line" =~ ^[[:space:]]*# ]] && continue
[[ -z "${line// }" ]] && continue
# Добаване на валидни ID-та
if [[ "$line" =~ ^[0-9]+$ ]]; then
containers+=("$line")
fi
done < "$CONTAINER_LIST"
fi
echo "${containers[@]}"
}
# Функция за получаване на списък с отдалечени бекъпи
get_remote_backups() {
local lxc_id=$1
ssh $SSH_OPTIONS "${PROXMOX_USER}@${PROXMOX_HOST}" \
"find ${REMOTE_BACKUP_PATH} -name 'vzdump-lxc-${lxc_id}-*.tar.zst' -type f -printf '%f\n'" 2>/dev/null | sort
}
# Функция за проверка дали бекъп е вече свален
is_downloaded() {
local backup_name=$1
grep -Fxq "$backup_name" "$DOWNLOADED_FILE"
}
# Функция за маркиране на бекъп като свален
mark_as_downloaded() {
local backup_name=$1
echo "$backup_name" >> "$DOWNLOADED_FILE"
}
# Функция за премахване от списъка със свалени
remove_from_downloaded() {
local backup_name=$1
grep -v "^${backup_name}$" "$DOWNLOADED_FILE" > "${DOWNLOADED_FILE}.tmp" && mv "${DOWNLOADED_FILE}.tmp" "$DOWNLOADED_FILE"
}
# Функция за изтриване на стари локални бекъпи
cleanup_old_backups() {
if [[ "$KEEP_DAYS" -gt 0 ]]; then
log "Изтривам локални бекъпи по-стари от $KEEP_DAYS дни..."
find "$LOCAL_BACKUP_PATH" -name "vzdump-lxc-*.tar.zst" -type f -mtime +$KEEP_DAYS -delete
fi
}
# Функция за сваляне на бекъпи
download_backups() {
local containers=($(load_containers))
if [[ ${#containers[@]} -eq 0 ]]; then
print_colored $RED "Няма конфигурирани контейнери за сваляне!"
return 1
fi
print_colored $BLUE "Започвам сваляне на бекъпи за контейнери: ${containers[*]}"
for lxc_id in "${containers[@]}"; do
log "Проверявам за нови бекъпи на LXC $lxc_id..."
remote_backups=$(get_remote_backups "$lxc_id")
if [[ -z "$remote_backups" ]]; then
log "Няма намерени бекъпи за LXC $lxc_id"
continue
fi
while IFS= read -r backup_file; do
[[ -z "$backup_file" ]] && continue
if ! is_downloaded "$backup_file"; then
log "Намерен нов бекъп: $backup_file"
log "Започвам сваляне..."
if rsync -avz --partial --progress -e "ssh $SSH_OPTIONS" \
"${PROXMOX_USER}@${PROXMOX_HOST}:${REMOTE_BACKUP_PATH}/${backup_file}" \
"${LOCAL_BACKUP_PATH}/"; then
log "Успешно свален: $backup_file"
mark_as_downloaded "$backup_file"
else
log "ERROR: Грешка при сваляне на $backup_file"
fi
else
log "Бекъп $backup_file вече е свален, прескачам..."
fi
done <<< "$remote_backups"
done
cleanup_old_backups
log "Завършено сваляне на бекъпи."
}
# Функция за качване на бекъпи
upload_backups() {
print_colored $BLUE "Започвам качване на локални бекъпи..."
local local_backups=$(find "$LOCAL_BACKUP_PATH" -name "vzdump-lxc-*.tar.zst" -type f -printf '%f\n' 2>/dev/null)
if [[ -z "$local_backups" ]]; then
print_colored $YELLOW "Няма намерени локални бекъпи за качване."
return 0
fi
while IFS= read -r backup_file; do
[[ -z "$backup_file" ]] && continue
print_colored $YELLOW "Проверявам дали $backup_file съществува на сървъра..."
# Проверка дали файлът съществува на отдалечения сървър
if ssh $SSH_OPTIONS "${PROXMOX_USER}@${PROXMOX_HOST}" \
"test -f ${REMOTE_BACKUP_PATH}/${backup_file}"; then
log "Бекъп $backup_file вече съществува на сървъра, прескачам..."
else
log "Качвам $backup_file на сървъра..."
if rsync -avz --partial --progress -e "ssh $SSH_OPTIONS" \
"${LOCAL_BACKUP_PATH}/${backup_file}" \
"${PROXMOX_USER}@${PROXMOX_HOST}:${REMOTE_BACKUP_PATH}/"; then
log "Успешно качен: $backup_file"
else
log "ERROR: Грешка при качване на $backup_file"
fi
fi
done <<< "$local_backups"
log "Завършено качване на бекъпи."
}
# Функция за управление на контейнери
manage_containers() {
while true; do
print_colored $BLUE "\n=== Управление на контейнери ==="
print_colored $YELLOW "1. Покажи текущи контейнери"
print_colored $YELLOW "2. Добави контейнер"
print_colored $YELLOW "3. Премахни контейнер"
print_colored $YELLOW "4. Редактирай файла с контейнери"
print_colored $YELLOW "5. Назад към главното меню"
read -p "Избери опция (1-5): " choice
case $choice in
1)
print_colored $GREEN "\nТекущи контейнери:"
local containers=($(load_containers))
if [[ ${#containers[@]} -eq 0 ]]; then
print_colored $RED "Няма конфигурирани контейнери."
else
for container in "${containers[@]}"; do
echo " - LXC $container"
done
fi
;;
2)
read -p "Въведи ID на контейнер за добавяне: " new_id
if [[ "$new_id" =~ ^[0-9]+$ ]]; then
echo "$new_id" >> "$CONTAINER_LIST"
print_colored $GREEN "Контейнер $new_id е добавен."
else
print_colored $RED "Невалиден ID! Използвай само цифри."
fi
;;
3)
read -p "Въведи ID на контейнер за премахване: " remove_id
if grep -q "^${remove_id}$" "$CONTAINER_LIST"; then
grep -v "^${remove_id}$" "$CONTAINER_LIST" > "${CONTAINER_LIST}.tmp" && mv "${CONTAINER_LIST}.tmp" "$CONTAINER_LIST"
print_colored $GREEN "Контейнер $remove_id е премахнат."
else
print_colored $RED "Контейнер $remove_id не е намерен в списъка."
fi
;;
4)
print_colored $YELLOW "Отварям $CONTAINER_LIST за редактиране..."
${EDITOR:-nano} "$CONTAINER_LIST"
;;
5)
break
;;
*)
print_colored $RED "Невалидна опция!"
;;
esac
done
}
# Функция за показване на статистики
show_statistics() {
print_colored $BLUE "\n=== Статистики ==="
local containers=($(load_containers))
print_colored $GREEN "Контейнери за наблюдение: ${#containers[@]}"
if [[ -f "$DOWNLOADED_FILE" ]]; then
local downloaded_count=$(wc -l < "$DOWNLOADED_FILE")
print_colored $GREEN "Свалени бекъпи: $downloaded_count"
fi
if [[ -d "$LOCAL_BACKUP_PATH" ]]; then
local local_count=$(find "$LOCAL_BACKUP_PATH" -name "vzdump-lxc-*.tar.zst" -type f | wc -l)
local local_size=$(du -sh "$LOCAL_BACKUP_PATH" 2>/dev/null | cut -f1)
print_colored $GREEN "Локални бекъпи: $local_count файла ($local_size)"
fi
print_colored $GREEN "Последна синхронизация: $(tail -1 "$LOG_FILE" 2>/dev/null | cut -d']' -f1 | tr -d '[')"
}
# Главно меню
show_menu() {
print_colored $BLUE "\n=== Proxmox Backup Sync Tool ==="
print_colored $YELLOW "1. Свали нови бекъпи"
print_colored $YELLOW "2. Качи локални бекъпи"
print_colored $YELLOW "3. Управление на контейнери"
print_colored $YELLOW "4. Покажи статистики"
print_colored $YELLOW "5. Почисти стари бекъпи"
print_colored $YELLOW "6. Покажи лог файл (последни 20 реда)"
print_colored $YELLOW "7. Изход"
}
# Главна функция
main() {
# Проверки при стартиране
if ! check_config; then
exit 1
fi
# Зареждане на конфигурацията
source "$CONFIG_FILE"
# Създаване на необходимите директории и файлове
mkdir -p "$LOCAL_BACKUP_PATH"
touch "$DOWNLOADED_FILE"
check_container_list
# Ако има аргументи от командния ред, изпълни директно
case "${1:-}" in
--download|-d)
download_backups
exit 0
;;
--upload|-u)
upload_backups
exit 0
;;
--help|-h)
echo "Употреба: $0 [ОПЦИЯ]"
echo "Опции:"
echo " -d, --download Свали нови бекъпи"
echo " -u, --upload Качи локални бекъпи"
echo " -h, --help Покажи тази помощ"
echo " (без опции) Покажи интерактивно меню"
exit 0
;;
esac
# Интерактивно меню
while true; do
show_menu
read -p "Избери опция (1-7): " choice
case $choice in
1)
download_backups
;;
2)
upload_backups
;;
3)
manage_containers
;;
4)
show_statistics
;;
5)
cleanup_old_backups
print_colored $GREEN "Почистването на стари бекъпи е завършено."
;;
6)
print_colored $BLUE "\n=== Последни записи в лога ==="
tail -20 "$LOG_FILE" 2>/dev/null || echo "Логът е празен."
;;
7)
print_colored $GREEN "Довиждане!"
exit 0
;;
*)
print_colored $RED "Невалидна опция!"
;;
esac
read -p "Натисни Enter за да продължиш..."
done
}
# Стартиране на главната функция
main "$@"
Благодарим ви за прочитането на статията! Ако намерихте информацията за полезна, можете да дарите посредством бутоните по-долу:
Donate ☕️ Дарете с PayPalDonate 💳 Дарете с Revolut