v1.8.60: multi-type status check + --add in skill + skill docs update
- _check_status_one: proper connectivity check per server type (SSH/SQL/Redis/Grafana/Prometheus/WinRM/RDP) - ping_server uses _check_status_one instead of paramiko-only - check_status shows server type column - skill-ssh.md: allow --add, document it, update --status description - CLAUDE.md: add --add/--remove/--set-note to command reference Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -136,6 +136,9 @@ tools/
|
|||||||
/ssh --list # Все серверы
|
/ssh --list # Все серверы
|
||||||
/ssh --info ALIAS # Инфо (без creds)
|
/ssh --info ALIAS # Инфо (без creds)
|
||||||
/ssh --status # Online/offline
|
/ssh --status # Online/offline
|
||||||
|
/ssh --add ALIAS IP PORT USER PASS # Добавить сервер
|
||||||
|
/ssh --remove ALIAS # Удалить сервер
|
||||||
|
/ssh --set-note ALIAS "desc" # Обновить заметки
|
||||||
```
|
```
|
||||||
|
|
||||||
## Конфигурация
|
## Конфигурация
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -13,7 +13,7 @@
|
|||||||
- Скрипт сам читает credentials, подключается, выполняет, возвращает результат
|
- Скрипт сам читает credentials, подключается, выполняет, возвращает результат
|
||||||
- **МАКСИМУМ 1 попытка** подключения. Если timeout/ошибка — сообщи, НЕ повторяй
|
- **МАКСИМУМ 1 попытка** подключения. Если timeout/ошибка — сообщи, НЕ повторяй
|
||||||
- fail2ban банит IP после 5-10 неудач — спам попытками УБЬЁТ доступ к серверу
|
- fail2ban банит IP после 5-10 неудач — спам попытками УБЬЁТ доступ к серверу
|
||||||
- **Серверы добавляются ТОЛЬКО через GUI** ServerManager, НЕ через CLI
|
- **Серверы можно добавлять** через `--add` (см. ниже) или через GUI ServerManager
|
||||||
|
|
||||||
## Аргументы
|
## Аргументы
|
||||||
|
|
||||||
@@ -31,10 +31,11 @@ python ~/.server-connections/ssh.py --list
|
|||||||
python ~/.server-connections/ssh.py --info ALIAS
|
python ~/.server-connections/ssh.py --info ALIAS
|
||||||
```
|
```
|
||||||
|
|
||||||
### Статус всех серверов (alias + online/offline)
|
### Статус всех серверов (alias + тип + online/offline)
|
||||||
```bash
|
```bash
|
||||||
python ~/.server-connections/ssh.py --status
|
python ~/.server-connections/ssh.py --status
|
||||||
```
|
```
|
||||||
|
Проверяет каждый сервер по его типу: SSH-подключение, SQL-коннект, Redis PING, HTTP health-check и т.д.
|
||||||
|
|
||||||
### Обновить заметки сервера
|
### Обновить заметки сервера
|
||||||
```bash
|
```bash
|
||||||
@@ -47,6 +48,15 @@ python ~/.server-connections/ssh.py --remove ALIAS
|
|||||||
```
|
```
|
||||||
**Спроси подтверждение у пользователя перед удалением!**
|
**Спроси подтверждение у пользователя перед удалением!**
|
||||||
|
|
||||||
|
### Добавить сервер
|
||||||
|
```bash
|
||||||
|
python ~/.server-connections/ssh.py --add ALIAS IP PORT USER PASSWORD [--note "описание"]
|
||||||
|
```
|
||||||
|
- Автоматически устанавливает SSH-ключ после добавления
|
||||||
|
- Обновляет `~/.ssh/config`
|
||||||
|
- **Спроси у пользователя все параметры перед добавлением!**
|
||||||
|
- Тип сервера по умолчанию — ssh. Для других типов (mariadb, redis и т.д.) — добавь через GUI
|
||||||
|
|
||||||
## SSH-команды (тип: ssh)
|
## SSH-команды (тип: ssh)
|
||||||
|
|
||||||
### Выполнить команду на сервере
|
### Выполнить команду на сервере
|
||||||
|
|||||||
101
tools/ssh.py
101
tools/ssh.py
@@ -314,9 +314,8 @@ def install_key(server: dict):
|
|||||||
|
|
||||||
def ping_server(server: dict):
|
def ping_server(server: dict):
|
||||||
try:
|
try:
|
||||||
client = get_client(server)
|
status = _check_status_one(server)
|
||||||
client.close()
|
print(f"{server['alias']}: {status}")
|
||||||
print(f"{server['alias']}: ONLINE")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"{server['alias']}: OFFLINE ({type(e).__name__})")
|
print(f"{server['alias']}: OFFLINE ({type(e).__name__})")
|
||||||
|
|
||||||
@@ -388,18 +387,102 @@ def server_info(alias: str):
|
|||||||
print(f"Notes: {notes}")
|
print(f"Notes: {notes}")
|
||||||
|
|
||||||
|
|
||||||
|
def _check_status_one(server: dict) -> str:
|
||||||
|
"""Check connectivity for a single server based on its type."""
|
||||||
|
stype = server.get("type", "ssh")
|
||||||
|
|
||||||
|
if stype in ("ssh", "telnet"):
|
||||||
|
client = get_client(server)
|
||||||
|
client.close()
|
||||||
|
return "ONLINE"
|
||||||
|
|
||||||
|
if stype in ("mariadb", "mysql", "mssql", "postgresql"):
|
||||||
|
host = server["ip"]
|
||||||
|
port = server.get("port", 3306)
|
||||||
|
user = server.get("user", "root")
|
||||||
|
password = server.get("password", "")
|
||||||
|
database = server.get("database", "")
|
||||||
|
if stype in ("mariadb", "mysql"):
|
||||||
|
import pymysql
|
||||||
|
conn = pymysql.connect(host=host, port=port, user=user, password=password,
|
||||||
|
database=database or None, connect_timeout=10)
|
||||||
|
elif stype == "mssql":
|
||||||
|
import pymssql
|
||||||
|
conn = pymssql.connect(server=host, port=port, user=user, password=password,
|
||||||
|
database=database or None, login_timeout=10)
|
||||||
|
elif stype == "postgresql":
|
||||||
|
import psycopg2
|
||||||
|
port = server.get("port", 5432)
|
||||||
|
conn = psycopg2.connect(host=host, port=port, user=user, password=password,
|
||||||
|
dbname=database or None, connect_timeout=10)
|
||||||
|
conn.close()
|
||||||
|
return "ONLINE"
|
||||||
|
|
||||||
|
if stype == "redis":
|
||||||
|
import redis as redis_lib
|
||||||
|
r = redis_lib.Redis(host=server["ip"], port=server.get("port", 6379),
|
||||||
|
password=server.get("password", "") or None,
|
||||||
|
db=server.get("db_index", 0), socket_timeout=10,
|
||||||
|
ssl=server.get("ssl", False))
|
||||||
|
r.ping()
|
||||||
|
r.close()
|
||||||
|
return "ONLINE"
|
||||||
|
|
||||||
|
if stype == "grafana":
|
||||||
|
import requests
|
||||||
|
host = server["ip"]
|
||||||
|
port = server.get("port", 3000)
|
||||||
|
protocol = "https" if server.get("ssl", False) else "http"
|
||||||
|
base_url = server.get("base_url", f"{protocol}://{host}:{port}")
|
||||||
|
resp = requests.get(f"{base_url.rstrip('/')}/api/health", timeout=10,
|
||||||
|
verify=server.get("ssl_verify", True))
|
||||||
|
resp.raise_for_status()
|
||||||
|
return "ONLINE"
|
||||||
|
|
||||||
|
if stype == "prometheus":
|
||||||
|
import requests
|
||||||
|
host = server["ip"]
|
||||||
|
port = server.get("port", 9090)
|
||||||
|
protocol = "https" if server.get("ssl", False) else "http"
|
||||||
|
base_url = server.get("base_url", f"{protocol}://{host}:{port}")
|
||||||
|
auth = None
|
||||||
|
user = server.get("user", "")
|
||||||
|
password = server.get("password", "")
|
||||||
|
if user and password:
|
||||||
|
auth = (user, password)
|
||||||
|
resp = requests.get(f"{base_url.rstrip('/')}/api/v1/status/buildinfo",
|
||||||
|
auth=auth, timeout=10, verify=server.get("ssl_verify", True))
|
||||||
|
resp.raise_for_status()
|
||||||
|
return "ONLINE"
|
||||||
|
|
||||||
|
if stype == "winrm":
|
||||||
|
session = _get_winrm_session(server)
|
||||||
|
result = session.run_cmd("echo ok")
|
||||||
|
if result.status_code == 0:
|
||||||
|
return "ONLINE"
|
||||||
|
return "OFFLINE"
|
||||||
|
|
||||||
|
# rdp/vnc — just TCP ping
|
||||||
|
import socket
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
sock.settimeout(10)
|
||||||
|
port = server.get("port", 3389 if stype == "rdp" else 5900)
|
||||||
|
sock.connect((server["ip"], port))
|
||||||
|
sock.close()
|
||||||
|
return "ONLINE"
|
||||||
|
|
||||||
|
|
||||||
def check_status():
|
def check_status():
|
||||||
_, servers = load_servers()
|
_, servers = load_servers()
|
||||||
print(f"{'Alias':<20} {'Status':<10}")
|
print(f"{'Alias':<20} {'Type':<12} {'Status':<10}")
|
||||||
print("-" * 30)
|
print("-" * 42)
|
||||||
for alias, s in servers.items():
|
for alias, s in servers.items():
|
||||||
|
stype = s.get("type", "ssh")
|
||||||
try:
|
try:
|
||||||
client = get_client(s)
|
status = _check_status_one(s)
|
||||||
client.close()
|
|
||||||
status = "ONLINE"
|
|
||||||
except Exception:
|
except Exception:
|
||||||
status = "OFFLINE"
|
status = "OFFLINE"
|
||||||
print(f"{alias:<20} {status:<10}")
|
print(f"{alias:<20} {stype:<12} {status:<10}")
|
||||||
|
|
||||||
|
|
||||||
def add_server(args):
|
def add_server(args):
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"""Version info for ServerManager."""
|
"""Version info for ServerManager."""
|
||||||
|
|
||||||
__version__ = "1.8.59"
|
__version__ = "1.8.60"
|
||||||
__app_name__ = "ServerManager"
|
__app_name__ = "ServerManager"
|
||||||
__author__ = "aibot777"
|
__author__ = "aibot777"
|
||||||
__description__ = "Desktop GUI for managing remote servers"
|
__description__ = "Desktop GUI for managing remote servers"
|
||||||
|
|||||||
Reference in New Issue
Block a user