Zamykanie połączenia po ponownym uruchomieniu za pomocą polecenia ssh


18

Używam reboot -fpolecenia zdalnie, aby wymusić ponowne uruchomienie komputera z systemem Unix. Problem polega na tym, że połączenie ssh pozostaje aktywne przez długi czas, co nie wiem dlaczego? Chcę zamknąć połączenie ssh natychmiast po ponownym uruchomieniu komputera i powrócić do mojej lokalnej powłoki. Jak mogę to zrobić? Zauważ, że polecenie restartu bez -fflagi nie działa.


1
Dlaczego nie po prostu wyjść z połączenia zdalnego (Ctrl + D) i pozwolić serwerowi uruchomić się ponownie bez konieczności oglądania zachęty powłoki?
gertvdijk

Jak mogę to zrobić za pomocą tego samego polecenia?
coffeMug

2
Znalazłem rozwiązanie, które może być pomocne również dla innych. Użyłem następującego polecenia, aby zamknąć połączenie zaraz po uruchomieniu polecenia dołączonego do ssh: ssh host ”, aby uruchomić na komputerze hosta> / dev / null &„ Nie w pełni rozumiem powód, dla którego to polecenie wymusza połączenie z blisko zrobione, ale przynajmniej było to dla mnie pomocne. Jeśli ktoś rozumie przekierowanie wyjścia polecenia do / dev / null i dlaczego zabija połączenie ssh, byłoby miło, gdyby mógł to wyjaśnić. :-)
coffeMug

ssh host "polecenie do uruchomienia na maszynie hosta> / dev / null &"
coffeMug

1
To nie jest odpowiedź na to pytanie, ale i tak warto wiedzieć: klient SSH ma szereg znaków kontrolnych, których można użyć między innymi do zabicia klienta. Znaki kontrolne są rozpoznawane tylko natychmiast po nowej linii, więc zacznij od naciśnięcia Enter. Następnie np. ~.Aby zakończyć sesję. Enter ~?na listę innych.
Tom

Odpowiedzi:


22

Polecenie reboot -fnigdy nie powraca (chyba że nie masz uprawnień do ponownego uruchomienia komputera). W momencie wydania klient SSH czeka na coś do zrobienia, na przykład:

  • serwer SSH powiadamia klienta, że ​​wydarzyło się coś, co wymaga jego uwagi, na przykład, że jest pewne wyjście do wyświetlenia lub że zdalne polecenie zostało zakończone;
  • pewne zdarzenie po stronie klienta, takie jak sygnał do przekazania;
  • uruchamia się licznik czasu, który powoduje wysłanie przez klienta wiadomości podtrzymującej połączenie (i zamknięcie połączenia, jeśli serwer nie odpowiada).

Ponieważ proces serwera SSH nie działa, klient SSH nie umrze, dopóki nie uruchomi się licznik czasu.

Jeśli uruchomisz ssh remotehost 'reboot -f >/dev/null &', to co się stanie, to:

  1. Zdalna powłoka uruchamia rebootpolecenie w tle.
  2. Ponieważ polecenie powłoki po stronie serwera zostało zakończone i nie ma procesu przechowującego deskryptor pliku dla standardowego wyjścia otwartego, serwer SSH zamyka połączenie.
  3. To rebootpolecenie powoduje ponowne uruchomienie komputera.

Nie jest to jednak niezawodne: w zależności od czasu krok 3 może się zdarzyć przed krokiem 2. Dodanie timera sprawia, że ​​jest to mało prawdopodobne:

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

Aby mieć absolutną pewność, że strona serwera jest zobowiązana do działania reboot, a jednocześnie upewniając się, że tak naprawdę nie uruchomi się ponownie przed powiadomieniem klienta o tym, że potrzebujesz, potrzebujesz dodatkowego powiadomienia, aby przejść z serwera do klienta. Można to wyprowadzić przez połączenie SSH, ale komplikuje się.


2
W przypadku, gdy ktoś szuka sposobu, aby to zrobić z poziomu hosta zdalnego (podobne rozwiązanie) (sleep 1 && sudo reboot &) && exit. Nawiasy odradzają podproces, który czeka jedną sekundę, a następnie inicjuje ponowne uruchomienie. Proces hosta natychmiast jednak kończy sesję ssh. Nie jestem guru skorupy, ale jak dotąd to dla mnie zadziałało.
Griddo,

@Griddo To działało fantastycznie i jest zgrabnym małym hackem. Kocham to. Dzięki za udostępnienie!
Joshua Pinter

5

Znalazłem to rozwiązanie, które działa najlepiej dla mnie.

Używaj -o "ServerAliveInterval 2"z sshpoleceniem:

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

Ta opcja powoduje, że po stronie klienta szturmuje serwer bezpiecznym kanałem co 2 sekundy. W końcu, w miarę ponownego uruchamiania, przestanie odpowiadać, a klient zerwie połączenie.


Dzięki Roman, działa jak magia! :)
stdcerr

3

Niektóre odpowiedzi były bliskie, ale prawidłowa odpowiedź to:

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

wyjaśnienie:

  • chcesz exitjako ostatnie polecenie, więc stan ostatniego polecenia to 0 (sukces). Możesz spać, jeśli chcesz, ale nie jest to konieczne
  • musisz uruchomić restart w tle, ponieważ w przeciwnym razie serwer zamknie połączenie i pojawi się błąd. Nadal uruchomi się ponownie w większości systemów, ale jeśli piszesz skrypt, zwracanym statusem będzie błąd (nie 0) nawet przy prawidłowym wykonaniu polecenia
  • uruchamianie w tle nie wystarczy, ponieważ stdini stdoutnadal są podłączone do terminala wirtualnego za pośrednictwem SSH, więc połączenie nie zostanie zamknięte. Musisz zrobić dwie dodatkowe rzeczy, aby sesja SSH zakończyła się, a komenda działała w tle.
    • 1) musisz przekierować stdouti stderraby /dev/nullnie były przekierowywane przez terminal wirtualny, który przechowuje sesję SSH. To jest &>/dev/nullczęść.
    • 2) musisz przekierować stdindo nieczytelnego pliku w ten sam sposób. Tak właśnie działa wbudowana powłoka nohup.

Gdy tylko komenda uruchomiona w tle zostanie odłączona od terminala pod każdym względem, exitzamknie sesję, a ponieważ na wirtualnym terminalu nie ma stdinlub stdoutpozostanie, SSH przerwie połączenie bez błędów.


1

Używam następującego polecenia:

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

Oto, co to robi:

  • Nakazuje maszynie ponowne uruchomienie w następnym momencie, ale nie podczas tej komendy
  • Wychodzi czysto z SSH
  • Utrzymuje SSH TTY przez cały czas, dzięki czemu sudo jest szczęśliwy i może działać poprawnie.

0

Czy wypróbowałeś następujące rzeczy?

# shutdown -r now

Uważam, że w niektórych systemach, nad którymi pracowałem w przełęczy, polecenie ponownego uruchomienia miało pewne problemy. Z drugiej strony nie mogę znaleźć niczego na stronie zamykania, która działałaby tak samo jak restart z flagą -f.


1
Tak, zamknięcie nie działa w maszynie, z którą próbuję się połączyć z dziwnych powodów. Dlatego używam restartu -f, aby wymusić zamknięcie i ponowne uruchomienie.
coffeMug

0

Co powiesz na wyjście z sesji ssh i zrestartowanie systemu za pomocą następnego polecenia:

ssh login@host "reboot -f"

Następnie naciśnij Ctrl + C, aby zakończyć ssh.


0

Znalazłem rozwiązanie, które może być pomocne również dla innych. Użyłem następującego polecenia, aby zamknąć połączenie zaraz po uruchomieniu polecenia dołączonego do ssh:

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

Nie do końca rozumiem powód, dla którego to polecenie wymusza zamknięcie połączenia, ale przynajmniej było to dla mnie pomocne. Jeśli ktoś zrozumie, dlaczego to zabija połączenie ssh; proszę wytłumacz.


0

Wymaga to 1-minutowego opóźnienia, ale działało dla mnie niezawodnie i rozwiązuje problem zawieszenia klienta SSH:

    $ sudo shutdown +1; logout

To planuje zamknięcie systemu na 1 minutę później, co daje czas na wylogowanie, a tym samym zakończenie SSH. Jeśli chcesz czekać tak mało czasu jak to możliwe, można wymienić +1ze HH:MMprzez pewien czas szybko zbliżającego się dnia, ale to może być trudne do czasu prawidłowo i może mieć do 59 sekundowym opóźnieniem.


0

Prostym sposobem, który znalazłem, jest polecenie zamknięcia / ponownego uruchomienia komputera jako zadania w tle (używając „&”), chroniąc go przed zamknięciem, gdy sesja kończy się za pomocą „nohup”, wraz z natychmiastowym wyjściem z powłoki / sesji:

nohup shutdown -r now & exit

W ten sposób klient SSH nie zawiesza się, ponieważ sesja kończy się natychmiast, a system zdalny uruchamia się ponownie asynchronicznie.


Lub
zastąp

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.