339 lines
18 KiB
Markdown
339 lines
18 KiB
Markdown
# Скилл /ssh — управление удалёнными серверами
|
||
|
||
Ты управляешь удалёнными серверами через универсальную CLI-утилиту.
|
||
Поддерживаются: SSH, SQL (MariaDB/MSSQL/PostgreSQL), Redis, S3/MinIO, Grafana, Prometheus, WinRM (PowerShell/CMD).
|
||
|
||
## ВАЖНО — Безопасность
|
||
|
||
- **НИКОГДА не читай файлы** в директории `~/.server-connections/` напрямую
|
||
- **НИКОГДА не читай** файлы `encryption.py`, `servers.json`, `settings.json`
|
||
- **НИКОГДА не выводи пароли, IP-адреса, логины, порты** пользователю и в контекст нейронки
|
||
- **НИКОГДА не используй** `--list-full` — он выводит IP/порты/логины в контекст AI
|
||
- **Все операции только через** `python ~/.server-connections/ssh.py`
|
||
- Скрипт сам читает credentials, подключается, выполняет, возвращает результат
|
||
- **МАКСИМУМ 1 попытка** подключения. Если timeout/ошибка — сообщи, НЕ повторяй
|
||
- fail2ban банит IP после 5-10 неудач — спам попытками УБЬЁТ доступ к серверу
|
||
- **Серверы можно добавлять** через `--add` (см. ниже) или через GUI ServerManager
|
||
|
||
## Аргументы
|
||
|
||
Пользователь передаёт через `$ARGUMENTS`. Разбери и выполни.
|
||
|
||
## КРИТИЧНО — СНАЧАЛА ПРОВЕРЬ ТИП СЕРВЕРА
|
||
|
||
**ПЕРЕД ЛЮБОЙ операцией** с сервером — **ОБЯЗАТЕЛЬНО** выполни `--list` и посмотри колонку `Type`.
|
||
**ЗАПРЕЩЕНО** угадывать тип сервера. MinIO/S3 — это НЕ SSH, Redis — это НЕ SSH, MariaDB — это НЕ SSH.
|
||
|
||
**Тип сервера определяет КАКИЕ команды использовать. Использование команд не того типа — СЛОМАЕТ операцию.**
|
||
|
||
| Тип | Команды | НЕ использовать |
|
||
|-----|---------|-----------------|
|
||
| `ssh` | `ALIAS "command"`, `--upload`, `--download`, `--ping`, `--install-key` | — |
|
||
| `telnet` | `ALIAS "command"` (без SFTP/sudo/ключей) | `--upload`, `--download` |
|
||
| `mariadb` / `mssql` / `postgresql` | `--sql`, `--sql-databases`, `--sql-tables` | `ALIAS "command"` |
|
||
| `redis` | `--redis`, `--redis-info`, `--redis-keys` | `ALIAS "command"` |
|
||
| `s3` (MinIO, AWS S3, и др.) | `--s3-buckets`, `--s3-ls`, `--s3-upload`, `--s3-download`, `--s3-delete`, `--s3-url`, `--s3-create-bucket` | `ALIAS "command"`, `--upload`, `--download` |
|
||
| `grafana` | `--grafana-dashboards`, `--grafana-alerts` | `ALIAS "command"` |
|
||
| `prometheus` | `--prom-query`, `--prom-targets`, `--prom-alerts` | `ALIAS "command"` |
|
||
| `winrm` | `--ps`, `--cmd` | `ALIAS "command"` |
|
||
| `rdp` / `vnc` | Только GUI | всё |
|
||
|
||
**`ALIAS "command"` (shell-команды типа ls, cat, mkdir) — ТОЛЬКО для типов `ssh` и `telnet`.**
|
||
|
||
```bash
|
||
# ❌ НЕПРАВИЛЬНО — MinIO/S3 это НЕ SSH, нельзя выполнять shell-команды
|
||
python ~/.server-connections/ssh.py "minio-alias" "ls /bucket"
|
||
python ~/.server-connections/ssh.py "minio-alias" "mkdir /bucket/folder"
|
||
|
||
# ✅ ПРАВИЛЬНО — S3-команды для типа s3
|
||
python ~/.server-connections/ssh.py --s3-ls "minio-alias" bucket
|
||
python ~/.server-connections/ssh.py --s3-upload "minio-alias" "D:/file.txt" bucket/folder/file.txt
|
||
|
||
# ❌ НЕПРАВИЛЬНО — Redis это НЕ SSH
|
||
python ~/.server-connections/ssh.py "redis-alias" "INFO"
|
||
|
||
# ✅ ПРАВИЛЬНО
|
||
python ~/.server-connections/ssh.py --redis-info "redis-alias"
|
||
|
||
# ❌ НЕПРАВИЛЬНО — MariaDB это НЕ SSH
|
||
python ~/.server-connections/ssh.py "mariadb-alias" "SHOW DATABASES"
|
||
|
||
# ✅ ПРАВИЛЬНО
|
||
python ~/.server-connections/ssh.py --sql-databases "mariadb-alias"
|
||
```
|
||
|
||
## Общие команды
|
||
|
||
### Список серверов (безопасный — alias, тип, группа, ключ, заметки)
|
||
```bash
|
||
python ~/.server-connections/ssh.py --list
|
||
```
|
||
|
||
### Информация о сервере (безопасная — без IP/логина/пароля/порта)
|
||
```bash
|
||
python ~/.server-connections/ssh.py --info ALIAS
|
||
```
|
||
|
||
### Статус всех серверов (alias + тип + online/offline)
|
||
```bash
|
||
python ~/.server-connections/ssh.py --status
|
||
```
|
||
Проверяет каждый сервер по его типу: SSH-подключение, SQL-коннект, Redis PING, HTTP health-check и т.д.
|
||
|
||
### Обновить заметки сервера
|
||
```bash
|
||
python ~/.server-connections/ssh.py --set-note ALIAS "описание сервера"
|
||
```
|
||
|
||
### Удалить сервер
|
||
```bash
|
||
python ~/.server-connections/ssh.py --remove ALIAS
|
||
```
|
||
**Спроси подтверждение у пользователя перед удалением!**
|
||
|
||
### Добавить сервер
|
||
```bash
|
||
python ~/.server-connections/ssh.py --add ALIAS IP PORT USER PASSWORD [--type ssh|telnet|mariadb|mssql|postgresql|redis|grafana|prometheus|winrm|rdp|s3] [--note "описание"] [--database DB] [--token TOKEN]
|
||
```
|
||
- Автоматически устанавливает SSH-ключ после добавления
|
||
- Обновляет `~/.ssh/config`
|
||
- **Спроси у пользователя все параметры перед добавлением!**
|
||
- Тип сервера по умолчанию — ssh. Для других типов (mariadb, redis и т.д.) — добавь через GUI
|
||
|
||
## SSH-команды (тип: ssh)
|
||
|
||
### Выполнить команду на сервере
|
||
```bash
|
||
python ~/.server-connections/ssh.py ALIAS "command"
|
||
```
|
||
Пример: `python ~/.server-connections/ssh.py investor "uptime"`
|
||
|
||
### Выполнить команду БЕЗ sudo
|
||
```bash
|
||
python ~/.server-connections/ssh.py ALIAS --no-sudo "command"
|
||
```
|
||
|
||
### Загрузить файл на сервер (ЕДИНСТВЕННЫЙ правильный способ)
|
||
```bash
|
||
python ~/.server-connections/ssh.py ALIAS --upload "D:/path/local/file" //remote/path/file
|
||
```
|
||
**ВАЖНО (Windows/Git Bash):** remote path ОБЯЗАТЕЛЬНО с двойным слешем `//home/...`, `//tmp/...`. Одинарный `/` будет сконвертирован Git Bash в Windows-путь и сломает SFTP.
|
||
**НИКОГДА не используй echo/base64/cat/stdin для передачи файлов — только `--upload`!**
|
||
|
||
### Скачать файл с сервера (ЕДИНСТВЕННЫЙ правильный способ)
|
||
```bash
|
||
python ~/.server-connections/ssh.py ALIAS --download //remote/path/file "D:/path/local/file"
|
||
```
|
||
Remote path тоже с `//`.
|
||
**НИКОГДА не используй scp/rsync/cat для скачивания — только `--download`!**
|
||
|
||
### Установить SSH-ключ на сервер
|
||
```bash
|
||
python ~/.server-connections/ssh.py ALIAS --install-key
|
||
```
|
||
|
||
### Проверить доступность сервера
|
||
```bash
|
||
python ~/.server-connections/ssh.py ALIAS --ping
|
||
```
|
||
|
||
## SQL-команды (типы: mariadb, mssql, postgresql)
|
||
|
||
### Выполнить SQL-запрос
|
||
```bash
|
||
python ~/.server-connections/ssh.py --sql ALIAS "SELECT * FROM users LIMIT 10"
|
||
```
|
||
|
||
### Список баз данных
|
||
```bash
|
||
python ~/.server-connections/ssh.py --sql-databases ALIAS
|
||
```
|
||
|
||
### Список таблиц
|
||
```bash
|
||
python ~/.server-connections/ssh.py --sql-tables ALIAS
|
||
python ~/.server-connections/ssh.py --sql-tables ALIAS mydb
|
||
```
|
||
|
||
## Redis-команды (тип: redis)
|
||
|
||
### Выполнить Redis-команду
|
||
```bash
|
||
python ~/.server-connections/ssh.py --redis ALIAS "GET mykey"
|
||
python ~/.server-connections/ssh.py --redis ALIAS "SET mykey myvalue"
|
||
```
|
||
|
||
### Информация о Redis
|
||
```bash
|
||
python ~/.server-connections/ssh.py --redis-info ALIAS
|
||
```
|
||
|
||
### Поиск ключей (SCAN)
|
||
```bash
|
||
python ~/.server-connections/ssh.py --redis-keys ALIAS "user:*"
|
||
```
|
||
|
||
## S3-команды (тип: s3) — MinIO, AWS S3, любое S3-совместимое хранилище
|
||
|
||
**MinIO = тип `s3`.** Когда пользователь говорит "MinIO" или "S3" — используй ТОЛЬКО `--s3-*` команды.
|
||
**НЕ пытайся** выполнять shell-команды (`ls`, `mkdir`, `cat`) на S3-серверах — это не SSH!
|
||
|
||
**Папки в S3 не существуют** — это префиксы. "Создать папку" = загрузить файл с префиксом в ключе (например `bucket/folder/file.txt`).
|
||
|
||
### Список бакетов
|
||
```bash
|
||
python ~/.server-connections/ssh.py --s3-buckets ALIAS
|
||
```
|
||
|
||
### Список объектов
|
||
```bash
|
||
python ~/.server-connections/ssh.py --s3-ls ALIAS bucket
|
||
python ~/.server-connections/ssh.py --s3-ls ALIAS bucket/prefix/
|
||
```
|
||
|
||
### Загрузить файл в S3
|
||
```bash
|
||
python ~/.server-connections/ssh.py --s3-upload ALIAS "D:/local/file" bucket/key
|
||
```
|
||
|
||
### Скачать файл из S3
|
||
```bash
|
||
python ~/.server-connections/ssh.py --s3-download ALIAS bucket/key "D:/local/file"
|
||
```
|
||
|
||
### Удалить объект
|
||
```bash
|
||
python ~/.server-connections/ssh.py --s3-delete ALIAS bucket/key
|
||
```
|
||
|
||
### Получить ссылку на файл (presigned URL)
|
||
```bash
|
||
python ~/.server-connections/ssh.py --s3-url ALIAS bucket/key
|
||
python ~/.server-connections/ssh.py --s3-url ALIAS bucket/key 86400
|
||
```
|
||
По умолчанию ссылка действует 1 час (3600 сек). Второй аргумент — время жизни в секундах (например 86400 = 24 часа).
|
||
|
||
### Создать бакет
|
||
```bash
|
||
python ~/.server-connections/ssh.py --s3-create-bucket ALIAS bucket-name
|
||
```
|
||
|
||
### Типичный workflow: "создай папку и залей файл"
|
||
```bash
|
||
# 1. Посмотри бакеты
|
||
python ~/.server-connections/ssh.py --s3-buckets ALIAS
|
||
# 2. "Создать папку" = просто загрузить файл с нужным путём (prefix)
|
||
python ~/.server-connections/ssh.py --s3-upload ALIAS "D:/file.txt" mybucket/newfolder/file.txt
|
||
# 3. Проверить
|
||
python ~/.server-connections/ssh.py --s3-ls ALIAS mybucket/newfolder/
|
||
# 4. Получить ссылку
|
||
python ~/.server-connections/ssh.py --s3-url ALIAS mybucket/newfolder/file.txt
|
||
```
|
||
|
||
## Grafana-команды (тип: grafana)
|
||
|
||
### Список дашбордов
|
||
```bash
|
||
python ~/.server-connections/ssh.py --grafana-dashboards ALIAS
|
||
```
|
||
|
||
### Список оповещений
|
||
```bash
|
||
python ~/.server-connections/ssh.py --grafana-alerts ALIAS
|
||
```
|
||
|
||
## Prometheus-команды (тип: prometheus)
|
||
|
||
### Выполнить PromQL-запрос
|
||
```bash
|
||
python ~/.server-connections/ssh.py --prom-query ALIAS "up"
|
||
python ~/.server-connections/ssh.py --prom-query ALIAS "rate(http_requests_total[5m])"
|
||
```
|
||
|
||
### Список целей (targets)
|
||
```bash
|
||
python ~/.server-connections/ssh.py --prom-targets ALIAS
|
||
```
|
||
|
||
### Список оповещений
|
||
```bash
|
||
python ~/.server-connections/ssh.py --prom-alerts ALIAS
|
||
```
|
||
|
||
## WinRM-команды (тип: winrm)
|
||
|
||
### PowerShell
|
||
```bash
|
||
python ~/.server-connections/ssh.py --ps ALIAS "Get-Process"
|
||
python ~/.server-connections/ssh.py --ps ALIAS "Get-Service | Where-Object {$_.Status -eq 'Running'}"
|
||
```
|
||
|
||
### CMD
|
||
```bash
|
||
python ~/.server-connections/ssh.py --cmd ALIAS "dir C:\\"
|
||
```
|
||
|
||
## Альтернативный способ (только SSH с установленным ключом)
|
||
```bash
|
||
unset SSH_ASKPASS && unset DISPLAY && ssh ALIAS "command"
|
||
```
|
||
|
||
## Поведение
|
||
|
||
- **Auto-sudo** (SSH): если user на сервере не root — команды автоматически оборачиваются в `sudo -S`, пароль подаётся через stdin. Тебе НЕ нужно добавлять `sudo` в команду
|
||
- **--no-sudo** (SSH): если команда не требует root (например `ls`, `cat`), используй `--no-sudo` для скорости
|
||
- **Windows SSH — автосанитизация**: при подключении к Windows серверам (определяется по alias/notes/os) Linux-команды автоматически транслируются в Windows-эквиваленты. Можно спокойно писать `ls`, `cat`, `grep`, `ps`, `df` — скрипт сам переведёт в `dir`, `type`, `Select-String`, `Get-Process`, и т.д. Pipe-цепочки (`cat file | grep error`) автоматически оборачиваются в PowerShell. Кодировка принудительно UTF-8 (`chcp 65001`). Команды `powershell ...`, `pwsh ...`, `cmd /c ...` проходят без изменений (passthrough). `sudo` автоматически удаляется, `chmod`/`chown` пропускаются с предупреждением
|
||
- **Timeout**: 120 секунд на SSH-команду, 10 секунд на SQL/Redis/HTTP-запросы, 15 секунд на подключение
|
||
- **SSH-ключ**: пробуется первым, fallback на пароль если ключ не подходит
|
||
- **Прогресс**: upload/download файлов >=1MB показывают 25/50/75% milestone, итог с размером/временем/скоростью
|
||
- **Тип сервера**: определяется автоматически из конфигурации. `--list` показывает тип каждого сервера
|
||
|
||
## Правила
|
||
|
||
- Отвечай на русском языке
|
||
- Показывай результат каждой операции
|
||
- При ошибках — объясняй причину и предлагай решение
|
||
- Если timeout — предложи проверить VPN/firewall/панель хостера
|
||
- Файлы создаваемые на сервере должны иметь права 664 (owner+group rw)
|
||
- При вопросе о серверах — СНАЧАЛА `--list`, потом `--info ALIAS` если нужны детали
|
||
- SQL-запросы: используй `LIMIT` для больших таблиц, чтобы не перегружать вывод
|
||
- Redis: используй SCAN, а не KEYS для больших баз
|
||
|
||
## КРИТИЧНО — Передача файлов
|
||
|
||
**ВСЕГДА используй `--upload` / `--download` для передачи файлов.** Это SFTP-протокол с автоматическими фичами:
|
||
|
||
- **Файлы >10MB:** chunked upload с resume — при обрыве продолжит с того места
|
||
- **Retry:** adaptive retry — до 30 попыток для больших файлов (exponential backoff, min 5s)
|
||
- **SHA256 верификация:** автоматическая проверка целостности после загрузки
|
||
- **Atomic rename:** запись в .part файл → проверка → переименование
|
||
- **Keepalive:** SSH keepalive каждые 15 секунд — не обрывается NAT/роутером
|
||
- **Прогресс:** 25/50/75% для файлов >1MB
|
||
- **Resume:** при повторном запуске `--upload` автоматически продолжает с .part файла (не начинает заново)
|
||
- **Windows SSH:** SHA256 через PowerShell `Get-FileHash`, пути автоматически нормализуются
|
||
|
||
```bash
|
||
# Загрузить файл на сервер (SFTP)
|
||
python ~/.server-connections/ssh.py ALIAS --upload "D:/local/file" //remote/path/file
|
||
|
||
# Скачать файл с сервера (SFTP)
|
||
python ~/.server-connections/ssh.py ALIAS --download //remote/path/file "D:/local/file"
|
||
```
|
||
|
||
**Поведение при обрыве:** соединение оборвалось → ждёт 5-30 сек → переподключается → проверяет .part файл на сервере → дозаливает с того места. Если файл полностью залит — проверяет SHA256 → atomic rename `.part` → финальный файл. Работает даже на нестабильных каналах (тестировано: 250MB через 6 reconnect'ов).
|
||
|
||
**ЗАПРЕЩЕНО** использовать shell-команды как **способ передачи файлов** на/с сервера:
|
||
- `echo "длинный_контент" > remote_file` — обрежет данные, сломает бинарники
|
||
- `base64` чанки через exec_command — ненадёжно, ломается на больших файлах (exit 127)
|
||
- `cat local_file | ssh` или stdin-пайпы — не работает через Paramiko exec_command
|
||
- Любые "креативные" shell-методы переноса содержимого файлов
|
||
|
||
**Это НЕ запрещает** использовать `echo`, `cat`, `base64` как обычные команды на сервере:
|
||
- `ALIAS "echo hello"` — OK (выполнение команды)
|
||
- `ALIAS "cat /etc/hosts"` — OK (чтение файла на сервере)
|
||
- `ALIAS "base64 -d config.b64 > config.bin"` — OK (операция на сервере)
|
||
|
||
**Если нужно передать файл на сервер** — используй `--upload`. Если файл уже существует локально — заливай напрямую. Если нужно создать новый файл с нуля — создай локально (Write tool), потом `--upload`.
|
||
|
||
**Если нужно прочитать файл с сервера** — используй `ALIAS "cat /path/file"` для маленьких текстовых, или `--download` для больших/бинарных.
|