Закриття з'єднання після виконання перезавантаження за допомогою команди ssh


18

Я використовую reboot -fкоманду віддалено, щоб примусити перезавантажити машину Unix. Проблема полягає в тому, що ssh-з'єднання залишається активним тривалий час, і я не знаю, чому? Я хочу закрити ssh-з'єднання відразу після перезавантаження машини і повернутися до своєї локальної оболонки. Як я можу це зробити? Зауважте, що команда перезавантаження без -fпрапора не працює.


1
Чому б просто не вийти з віддаленого з'єднання (Ctrl + D) і не дозволити серверу перезавантажуватися без того, щоб вам було потрібно дивитися підказку оболонки?
gertvdijk

Як я можу це зробити в одній команді?
coffeMug

2
Я знайшов рішення для цього, яке може бути корисним і для інших. Я використовував таку команду, щоб закрити з'єднання відразу після запуску команди, прикріпленої до ssh: ssh host "команда для запуску на машині хоста> / dev / null &" Я не повністю розумію причину, через яку ця команда змушує з'єднання завершено, але, принаймні, мені це було корисно. Якщо хтось розуміє направлення виводу команди на / dev / null і чому це вбиває ssh-з'єднання, було б добре, якщо він / вона може це пояснити. :-)
coffeMug

команда ssh хост "запустити на хост-машині> / dev / null &"
coffeMug

1
Це не відповідь на це питання, але корисно все-таки знати: Клієнт SSH має ряд контрольних символів, які можуть бути використані, серед іншого, для вбивства клієнта. Контрольні символи розпізнаються лише відразу після нового рядка, тому почніть з натискання Enter. Потім, наприклад, ~.припинити сеанс. Enter ~?для списку інших.
Том

Відповіді:


22

Команда reboot -fніколи не повертається (якщо ви не мали дозволу на перезавантаження). У момент, коли він видається, клієнт SSH чекає, що можна зробити, що може бути:

  • сервер SSH, який сповіщає клієнта про те, що сталося щось, що вимагає його уваги, наприклад, є якийсь вихід для відображення, або про те, що віддалена команда закінчена;
  • якась подія на стороні клієнта, наприклад, сигнал для ретрансляції;
  • таймер запускається, щоб клієнт надіслав повідомлення про збереження (і закрити з'єднання, якщо сервер не відповість).

Оскільки процес SSH-сервера мертвий, клієнт SSH не помре, поки таймер не запуститься.

Якщо ти біжиш ssh remotehost 'reboot -f >/dev/null &', то відбувається:

  1. Віддалена оболонка запускає rebootкоманду у фоновому режимі.
  2. Оскільки команда оболонки на стороні сервера завершена і не існує жодного процесу, утримуючи дескриптор файлу для стандартного виводу відкритим, сервер SSH закриває з'єднання.
  3. rebootКоманда змушує машину перезавантаження.

Однак це не є надійним: залежно від часу, крок 3 може статися перед кроком 2. Додавання таймера робить це малоймовірним:

ssh remotehost '{ sleep 1; reboot -f; } >/dev/null &'

Щоб бути абсолютно впевненим, що сторона сервера зобов’язана працювати reboot, переконуючись, що вона насправді не перезавантажується, перш ніж сповістити клієнта про її вчинення, вам потрібно додаткове повідомлення про перехід із сервера до клієнта. Це може бути виведено через з'єднання SSH, але воно ускладнюється.


2
У разі , якщо хто - то шукає спосіб зробити це зсередини віддаленого хоста (аналогічний розчин): (sleep 1 && sudo reboot &) && exit. В дужках створюється підпроцес, який чекає одну секунду, а потім ініціює перезавантаження. Однак хост-процес негайно припиняє сеанс ssh. Я не гуру оболонок, але це для мене працювало досі.
Гріддо

@Griddo Це спрацювало фантастично і є акуратним маленьким хаком. Я це люблю. Дякую, що поділились!
Джошуа Пінтер

5

Я знайшов це рішення найкращим для мене.

Використовуйте -o "ServerAliveInterval 2"зі своєю sshкомандою так:

$ ssh -o "ServerAliveInterval 2" root@remotehost reboot

Зазначена опція змушує клієнтську сторону кожувати сервер по захищеному каналу кожні 2 секунди. Згодом, коли перезавантаження триватиме, воно перестане реагувати, і клієнт зірве з'єднання.


Дякую Роману, працює як магія! :)
stdcerr

4

Деякі відповіді були близькими, але правильна відповідь:

ssh user@192.168.0.130 "nohup sudo reboot &>/dev/null & exit"

пояснення:

  • ви хочете exitяк остання команда, тому статус останньої команди 0 (успіх). Ви можете передбачити сон, якщо хочете, але це не обов'язково
  • вам потрібно запустити перезавантаження у фоновому режимі, оскільки в іншому випадку сервер закриє з'єднання, і ви отримаєте помилку. Він все одно перезавантажиться в більшості систем, але якщо ви створюєте сценарій, статус повернення буде помилкою (не 0), навіть якщо команда виконана належним чином
  • що працюють на задньому плані не вистачає, як stdinі stdoutвсі ще прив'язані до віртуального терміналу через SSH, тому з'єднання не буде закрито. Вам потрібно зробити дві додаткові речі, щоб сеанс SSH закінчився і залишити команду, що працює на тлі.
    • 1) вам потрібно переадресувати stdoutі stderrщоб /dev/nullвони не перенаправлялися віртуальним терміналом, який проводить сеанс SSH. Це &>/dev/nullчастина.
    • 2) вам потрібно переспрямувати stdinв нечитабельний файл таким же чином. Саме це і nohupробить вбудована оболонка .

Щойно команда, запущена на тлі, віддаленого від терміналу всіма способами, exitзакриє сеанс, і оскільки у віртуальному терміналі немає stdinабо stdoutзалишилося SSH, припинить з'єднання без помилок.


1

Я використовую таку команду:

ssh -t <hostname> 'sudo shutdown --reboot 0 && exit'

Ось що це робить:

  • Він інструктує машину перезавантажуватися в наступний момент, але не під час виконання цієї команди
  • Чисто виходить із SSH
  • Підтримує SSH TTY весь час, тому sudo раді та може виконувати належним чином.

0

Ви спробували наступне

# shutdown -r now

Я вважаю, що в деяких системах, над якими я працював у проході, команда перезавантаження мала деякі проблеми. Тоді знову я не можу знайти нічого на сторінці закриття, яке б зробило те саме, що перезавантажити прапором -f.


1
Так, відключення не працює в машині, до якої я намагаюся підключитися з якихось дивних причин. Ось чому я використовую перезавантаження -f для примусового відключення та перезапуску.
coffeMug

0

Як щодо виходу із сеансу ssh та перезавантаження системи за допомогою наступної команди:

ssh login@host "reboot -f"

Після цього просто натисніть Ctrl + C для припинення ssh.


0

Я знайшов рішення для цього, яке може бути корисним і для інших. Я використовував таку команду, щоб закрити з'єднання відразу після запуску команди, прикріпленої до ssh:

ssh host "command to run on the host machine > /dev/null &"

Я не точно розумію причину, через яку ця команда змушує зв’язок закритись, але, принаймні, це було мені корисно. Якщо хтось розуміє, чому це вбиває ssh-з'єднання; Будь ласка, поясніть.


0

Це вимагає затримки на 1 хвилину, але надійно працює для мене і вирішує проблему зависання клієнта SSH:

    $ sudo shutdown +1; logout

Це планує відключення системи на 1 хвилину пізніше, що дає час для завершення виходу, а отже і припинення SSH. Якщо ви хочете , щоб чекати , як мало часу , як це можливо, ви могли б замінити +1з HH:MMдля швидко наближається часу доби , але це може бути складно часу правильно і може мати до другої затримки 59.


0

Простий спосіб, який я знайшов, - це командувати вимкненням / перезавантаженням як фоновим завданням (використовуючи «&»), захищаючи його від закриття, коли сеанс закривається «nohup», а також негайний вихід оболонки / сеансу:

nohup shutdown -r now & exit

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


Або замініть еквівалент вашої системи на "shutdown -r now" на перезавантаження ....
MikeW

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.