Чому консолі іноді навішуються назавжди, коли розривається з'єднання SSH?


89

Я бачив це з великою кількістю консолей (на Linux, Mac, ...) і з безліччю різних машин у багатьох різних мережах. Я ніколи не можу точно визначити причину, чому це трапляється: все, що вам потрібно зробити, - це увійти до машини через SSH. Якщо з'єднання з якоїсь причини перерветься (для простоти, скажімо, мережевий кабель був вирваний), то іноді консоль просто зависає назавжди - в інший час вона просто чудово виходить до батьківської оболонки.

Це так дратує, коли це відбувається (наприклад, ви втрачаєте історію команд.) Чи може бути секретна комбінація клавіш, яка може змусити вихід (Ctrl-C або Ctrl-D не працюють)? І в чому причина цієї випадкової «помилки» у всіх реалізаціях?


Цей потік видається доцільним згадати Mosh (Mobile Shell), який добре справляється з відмовами підключення, включаючи роумінг (зміна IP) та інші речі.
Ciprian Tomoiagă

Відповіді:


137

Існує "секретна" комбінація клавіш, щоб змусити вихід: ~) З замороженого сеансу натисніть ці клавіші в порядку: Enter~.Тильда (лише після нового рядка) розпізнається ssh-клієнтом як послідовність виходу, і період повідомляє про Клієнт припиняє свою діяльність без зайвих помилок.

Поведінка, що триває в зв'язку з питаннями зв'язку, не є помилкою, сеанс SSH зависає з надією, що інша сторона повернеться. Якщо мережа розривається, іноді навіть через дні ви можете отримати сеанс SSH. Звичайно, ви можете конкретно сказати йому відмовитися і померти з послідовністю, наведеною вище. Ви також можете виконати різні дії, такі як встановлення тайм-аутів в режимі "живого життя" у вашому клієнті, щоб, якщо він не мав активного посилання протягом певного часу, він відключається самостійно, але поведінка за замовчуванням - це залишатися як як можна підключено!

Редагувати: Ще одне корисне застосування цього ключа переривання - привернути увагу місцевого клієнта ssh і передати його на хвилину, щоб повернутися до локальної оболонки - скажімо, щоб отримати щось із вашої історії -, а потім примусити його працювати далі. Enter~ Ctrl+, Zщоб відправити ssh-клієнта до чергової черги завдань локальної оболонки, тоді fgяк звичайно, щоб повернути його.

Редагувати: обмінюючись вкладеними сесіями SSH, ви можете додати кілька символів тильду, щоб вирватися лише з одного з сеансів SSH у ланцюжку, але зберегти інші. Наприклад, якщо ви вкладені в 3 рівні (тобто ви сш з локального-> Machine1-> Machine2-> Machine3), Enter~.ви повернетесь до свого локального сеансу, Enter~~.залишите вас у Machine1 і Enter~~~.залишите вас у Machine2 . Це працює і для інших послідовностей евакуації, таких як тимчасове переміщення сеансу ssh на фон. Вищезазначене працює для будь-якого рівня вкладення, просто додаючи більше тильди.

Нарешті, ви можете використовувати Enter~?для друку довідкового меню доступних команд евакуації.

TL; DR - підтримувані команди втечі підтримуються послідовностями:

 ~.   - terminate connection (and any multiplexed sessions)
 ~B   - send a BREAK to the remote system
 ~C   - open a command line
 ~R   - request rekey
 ~V/v - decrease/increase verbosity (LogLevel)
 ~^Z  - suspend ssh
 ~#   - list forwarded connections
 ~&   - background ssh (when waiting for connections to terminate)
 ~?   - this message
 ~~   - send the escape character by typing it twice
(Note that escapes are only recognized immediately after newline.)

11
+1 за те, що знає пароль dodecatouple-secret-probation для стрільби sshd в голову. Ви дізналися про це так само, як і я (затуманивши ~/.somethingorotherпісля удару ввійти)?
voretaq7

2
@ voretaq7: Ні, я не був таким розумним, але коли хтось зрозумів мене, я пішов "Дійсно? Так ось що відбувалося в усі ті часи, коли моя оболонка ходила БАГ! Без причини, коли я набирав текст?" . Це не звичайна послідовність, за винятком помилок, про які ви згадуєте, але це може статися.
Калеб

14
Під яким "секрет" він означає "на сторінці чоловіка".
larsks

4
Хоча багато людей не знають про це, це справді секрет на простоті. man sshвисвітлює це під ESCAPE CHARACTERSрозділом. ~.(Відключити) та ~^Z(фоновий ssh) дуже зручні.
Стефан Ласєскі

9
Звичайно, це на сторінці чоловіка :) Я вжив лише слово секрет, оскільки це робив ОП, і я використовував мову в щоках. Проблема цієї функції полягає в тому, що люди не знають, де її шукати, вони очікують, що контрольні символи та такі сигнали будуть частиною оболонки чи подібними. Як тільки ви знаєте, куди шукати або навіть що питати, звичайно, це є.
Калеб

12

SSH пропонує зберегти живий заклад. Додайте наступне до свого локального ~/.ssh/config(створіть, якщо його немає):

ServerAliveInterval 15
ServerAliveCount 3

Цей параметр встановлює постійний сигнал, що надходить кожні 15 секунд через захищений тунель. Після трьох послідовних відмов клієнт SSH вийде.

Зауважте, що в деяких системах (включаючи macOS 10.14) замість цього потрібно:

ServerAliveInterval 15
ServerAliveCountMax 3

Взяте з цієї відповіді на ask.ubuntu: https://askubuntu.com/a/29967/30266


9

Те, що він висить, - це функція TCP, а не SSH. У додатку немає способу знати, що сеанс / з'єднання TCP було розірвано, якщо TCP не повідомить програму за допомогою з'єднання, що з'єднання більше не існує. З точки зору кожного хоста, сеанс TCP все ще знаходиться у встановленому стані, і нічого не можна сказати, що тривалий непрацюючий (без потоку даних) сеанс не є дійсним, окрім RST або відсутності відповіді на пакет пакета TCP-keepalive (який не реалізується повсюдно). Мені здається, це не помилка в SSH, я б очікував такої поведінки.


5

Якщо підключення належним чином підключено, будь-який магічний натискання клавіші не пройде, оскільки з'єднання вже висіло перед тим, як видавати натискання клавіш. Ви можете сказати клієнтові припинити роботу, але це не вплине на історію, що зберігається (чи ні) на кінці сервера.

Хоча це насправді не відповідає на запитання, це може допомогти зменшити наслідки зависання підключення: коли я працюю віддалено (і навіть зазвичай, коли мене немає), я перебігаю screenbyobuобгорткою або без неї, залежно від її наявності) так що якщо є якесь з'єднання, моє сеанс з усією його історією зберігається і доступний у тому стані, який я покинув, коли я знову підключався.


6
Ваша пропозиція щодо екрана чудова, але перший біт насправді не стосується проблеми. Вам не потрібно діставати ключі до віддаленої сторони, вам потрібно лише дістати їх до клієнта LOCAL ssh! ОП хочуть повернути його локальну оболонку, включаючи історію. SSH переймає його і не реагує на нормальні послідовності розриву, такі як CTRL-C, тому що він передає ці дані. Існує спосіб пройти та припинити місцевого клієнта, дивіться мою відповідь. Історія на локальному кінці зазвичай все одно зберігається, якщо ви знову ввійдете в систему, залежно від конфігурації оболонки.
Калеб

2
@Caleb: у питанні конкретно згадується історія втрати, а історія команд зберігається на стороні сервера. Щоб сказати серверу робити щось інше з історією, вам потрібно отримати повідомлення на сервер, щоб він сказав щось інше з історією. Звичайно, існують способи змусити bash (та деякі інші оболонки) записувати рядки історії негайно, а не збирати їх в оперативній пам'яті, поки користувач належним чином не створить оболонку з exit/ logoutщо дозволить вирішити проблему історії без використання screen.
Девід Спіллетт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.