diff --git a/core/color.py b/core/color.py index edd1fda..7389ce3 100644 --- a/core/color.py +++ b/core/color.py @@ -112,6 +112,19 @@ def prompt(text, default=None): sys.exit(130) +def prompt_password(text): + """Скрытый ввод пароля/passphrase. В pipe — обычный prompt с предупреждением.""" + import getpass + try: + return getpass.getpass(f"{yellow('❯')} {text} ") + except EOFError: + print(f"{yellow('⚠')} Ввод пароля в pipe не поддерживается скрытым режимом. Используем обычный ввод.") + return prompt(text) + except KeyboardInterrupt: + print(f"\n{yellow('⚠')} Прервано пользователем (Ctrl+C)") + sys.exit(130) + + def confirm(text, default="y"): """Да/нет с обработкой EOF. В pipe — возвращает default.""" yn = "Y/n" if default.lower() == "y" else "y/N" diff --git a/source/source.py b/source/source.py index 6ea2348..64e72f5 100644 --- a/source/source.py +++ b/source/source.py @@ -10,7 +10,7 @@ import tarfile import time import sys from datetime import datetime -from core.color import header, subheader, success, warn, error as cerror, info, step, prompt, confirm, divider, log_cmd +from core.color import header, subheader, success, warn, error as cerror, info, step, prompt, prompt_password, confirm, divider, log_cmd from core import state from core.runner import run from discover.docker import discover_docker, get_container_pid @@ -380,7 +380,7 @@ def do_transfer_offer(): state.set_stage("TRANSFER", target_host=host, target_user=user, target_port=port_int, ssh_key=key_path) else: # Нет SSH-ключа — спрашиваем пароль и пробуем sshpass - password = prompt(f"Введите пароль для {user}@{host} (или Enter для отмены)") + password = prompt_password(f"Пароль для {user}@{host} (Enter для отмены)") if not password: state.set_error("ssh_key_setup", "", "Пароль не введён", suggestion="Запустите docker-migrate --resume или настройте SSH-ключ") raise RuntimeError("Пароль не введён. Установите SSH-ключ или введите пароль.") diff --git a/transfer/ssh.py b/transfer/ssh.py index b9decbc..dc50c6a 100644 --- a/transfer/ssh.py +++ b/transfer/ssh.py @@ -82,7 +82,7 @@ def test_keys_against_target(host, user, port, keys): else: # Проверим, не passphrase ли if "passphrase" in err.lower() or "password" in err.lower(): - warn(f" ! Ключ '{label}' требует passphrase (зашифрован). Пропускаем (нужен ssh-agent).") + warn(f" ! Ключ '{label}' требует passphrase (зашифрован). Можно ввести passphrase позже.") else: info(f" ✗ Ключ '{label}' не подходит ({err.strip()[:60]}).") return working @@ -225,7 +225,8 @@ def pick_or_setup_ssh_key(host, user, port): ok, _, err = check_ssh_connectivity(host, user, port, key_path=k["private"]) if not ok and ("passphrase" in err.lower() or "password" in err.lower()): if confirm(f"Ключ '{label}' зашифрован. Ввести passphrase и попробовать", default="y"): - pw = prompt(f"Passphrase для {label} (ввод скрыт)") + from core.color import prompt_password + pw = prompt_password(f"Passphrase для {label}") if pw and try_key_with_passphrase(k["private"], pw): # После ssh-add ключ должен работать ok2, _, _ = check_ssh_connectivity(host, user, port, key_path=k["private"])