<===
2026-02-23 17:30:11
## Скрипт для переключения OpenVPN‑клиентов (Manjaro, systemd)
Конфиги: `/etc/openvpn/client/*.conf`
Сервисы: `openvpn-client@NAME.service` (NAME = имя конфига без `.conf`).
### Скрипт `/usr/local/bin/vpnsw`
```bash
#!/usr/bin/env bash
SERVICE_PREFIX="openvpn-client"
CONF_DIR="/etc/openvpn/client"
get_active_vpn() {
systemctl list-units --type=service --state=running \
| awk -v p="${SERVICE_PREFIX}@" '$1 ~ "^"p {print $1}' \
| sed -E "s/^${SERVICE_PREFIX}@([^\.]+)\.service/\1/" | head -n1
}
show_status() {
local active
active="$(get_active_vpn)"
echo "Текущий VPN-сервис: ${active:-нет}"
ip -brief a show tun0 2>/dev/null || echo "tun0: не найден"
echo
}
stop_active() {
local active
active="$(get_active_vpn)"
if [[ -n "$active" ]]; then
echo "Останавливаю ${SERVICE_PREFIX}@${active}.service ..."
sudo systemctl stop "${SERVICE_PREFIX}@${active}.service"
else
echo "Активных ${SERVICE_PREFIX}@*.service не найдено."
fi
}
stop_all() {
echo "Останавливаю все ${SERVICE_PREFIX}@*.service ..."
sudo systemctl stop "${SERVICE_PREFIX}"@*.service 2>/dev/null || true
sleep 2
show_status
}
start_vpn() {
local name="$1"
if [[ -z "$name" ]]; then
echo "Не указано имя профиля."
return 1
fi
if [[ ! -f "${CONF_DIR}/${name}.conf" ]]; then
echo "Конфиг ${CONF_DIR}/${name}.conf не найден."
return 1
fi
echo "Стартую ${SERVICE_PREFIX}@${name}.service ..."
sudo systemctl start "${SERVICE_PREFIX}@${name}.service"
sleep 2
sudo systemctl status "${SERVICE_PREFIX}@${name}.service" --no-pager -n 5
}
menu_mode() {
while true; do
show_status
shopt -s nullglob
local files=("${CONF_DIR}"/*.conf)
shopt -u nullglob
if (( ${#files[@]} == 0 )); then
echo "В ${CONF_DIR} нет *.conf"
return 1
fi
local names=()
local f
for f in "${files[@]}"; do
f="${f##*/}" # io.conf
f="${f%.conf}" # io
names+=("$f")
done
# 1: без VPN, далее профили, последний пункт — Выход
local options=("без VPN" "${names[@]}" "Выход")
PS3="Выбери VPN (1 — без VPN, ${#options[@]} — выход): "
select opt in "${options[@]}"; do
if [[ "$opt" == "без VPN" ]]; then
stop_all
break # обновить статус и меню
fi
if [[ "$opt" == "Выход" ]]; then
echo "Выход."
return 0
fi
if [[ -z "$opt" ]]; then
echo "Неверный выбор: $REPLY"
break # перерисовать меню
fi
local name="$opt"
stop_active
start_vpn "$name"
echo
break # вернуться в while -> обновить статус и меню
done
done
}
main() {
local VPN_NAME="$1"
# режим: без VPN с CLI
if [[ "$VPN_NAME" == "0" || "$VPN_NAME" == "none" || "$VPN_NAME" == "off" ]]; then
stop_all
exit 0
fi
# режим: сразу включить профиль
if [[ -n "$VPN_NAME" ]]; then
stop_active
start_vpn "$VPN_NAME"
show_status
else
# интерактивное меню
menu_mode
fi
}
main "$@"
```
### Установка
```bash
sudo nano /usr/local/bin/vpnsw # вставить скрипт
sudo chmod +x /usr/local/bin/vpnsw
```
### Использование
```bash
vpnsw # меню: список профилей по *.conf
vpnsw io # сразу переключиться на io
vpnsw uqu # сразу на uqu
```
Back to list