Fechando a conexão após executar a reinicialização usando o comando ssh

18

Estou usando o reboot -fcomando remotamente para forçar a reinicialização de uma máquina Unix. O problema é que a conexão ssh permanece ativa por um longo tempo, e não sei por quê? Quero fechar a conexão ssh imediatamente após reiniciar a máquina e retornar ao meu shell local. Como eu posso fazer isso? Observe que o comando reboot sem -fsinalizador não funciona.

coffeMug
fonte
1
Por que não sair da sua conexão remota (Ctrl + D) e deixar o servidor reiniciar sem que você precise assistir ao prompt do shell?
gertvdijk
Como posso fazer isso no mesmo comando?
coffemug
2
Encontrei uma solução para isso que também pode ser útil para outras pessoas. Usei o seguinte comando para fechar a conexão logo após iniciar o comando anexado ao ssh: ssh host "comando para executar na máquina host> / dev / null &" Não entendo completamente o motivo pelo qual esse comando força a conexão a fechar feito, mas pelo menos foi útil para mim. Se alguém entender a direção da saída do comando para / dev / null e por que ela mata a conexão ssh, seria bom se ele pudesse explicá-la. :-)
coffemug
ssh host "comando para executar na máquina host> / dev / null &"
coffeMug 12/12/12
1
Não é uma resposta para esta pergunta, mas é útil saber de qualquer maneira: O cliente SSH possui uma série de caracteres de controle que podem ser usados, entre outras coisas, para matar o cliente. Os caracteres de controle são reconhecidos apenas imediatamente após uma nova linha, então comece pressionando Enter. Então, por exemplo, ~.para encerrar a sessão. Enter ~?para uma lista de outras pessoas.
Tom

Respostas:

22

O comando reboot -fnunca retorna (a menos que você não tenha permissão para causar uma reinicialização). No momento em que é emitido, o cliente SSH está aguardando algo para fazer, o que pode ser:

  • o servidor SSH notificando o cliente que algo aconteceu que requer atenção, por exemplo, que há alguma saída a ser exibida ou que o comando remoto foi concluído;
  • algum evento no lado do cliente, como um sinal para retransmitir;
  • um timer sendo acionado para fazer com que o cliente envie uma mensagem de manutenção permanente (e feche a conexão se o servidor não responder).

Como o processo do servidor SSH está inoperante, o cliente SSH não morre até que o cronômetro seja acionado.

Se você executar ssh remotehost 'reboot -f >/dev/null &', o que acontece é:

  1. O shell remoto inicia o rebootcomando em segundo plano.
  2. Como o comando shell do lado do servidor foi encerrado e não há processo mantendo o descritor de arquivo da saída padrão aberto, o servidor SSH fecha a conexão.
  3. O rebootcomando faz com que a máquina seja reinicializada.

No entanto, isso não é confiável: dependendo do tempo, a etapa 3 pode ocorrer antes da etapa 2. A adição de um timer torna isso improvável:

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

Para ter certeza absoluta de que o lado do servidor está comprometido com a execução reboot, assegurando-se de que ele não seja realmente reiniciado antes de notificar o cliente de que está comprometido, você precisa de uma notificação adicional para passar do servidor para o cliente. Isso pode ser emitido através da conexão SSH, mas fica complicado.

Gilles 'SO- parar de ser mau'
fonte
2
No caso de alguém está procurando uma maneira de fazer isso a partir do host remoto (solução similar): (sleep 1 && sudo reboot &) && exit. Os parênteses geram um subprocesso, que espera um segundo e, em seguida, inicia a reinicialização. O processo host, no entanto, termina imediatamente a sessão ssh. Eu não sou um guru de conchas, mas isso funcionou para mim até agora.
Griddo 12/12/16
@Griddo Isso funcionou fantástico e é um pequeno truque. Eu amo isso. Obrigado por compartilhar!
Joshua Pinter
5

Encontrei esta solução para executar o melhor para mim.

Use -o "ServerAliveInterval 2"com seu sshcomando, assim:

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

A opção mencionada faz o lado do cliente cutucar o servidor em um canal seguro a cada 2 segundos. Eventualmente, à medida que a reinicialização prossegue, ele para de responder e o cliente interrompe a conexão.

Roman Saveljev
fonte
Obrigado Roman, funciona como mágica! :)
stdcerr 31/07
3

Algumas respostas foram próximas, mas a resposta certa é:

ssh [email protected] "nohup sudo reboot &>/dev/null & exit"

explicação:

  • você deseja exitcomo o último comando para que o status do último comando seja 0 (êxito). Você pode adormecer se desejar, mas não é necessário
  • você precisa executar a reinicialização em segundo plano, caso contrário, o servidor fechará a conexão e você receberá um erro. Ele ainda será reiniciado na maioria dos sistemas, mas se você estiver executando o script, o status de retorno será um erro (não 0), mesmo com o comando sendo executado corretamente.
  • a execução em segundo plano não é suficiente, pois o stdine stdoutainda está conectado ao terminal virtual por meio do SSH; portanto, a conexão não será fechada. Você precisa fazer duas coisas extras para que a sessão SSH termine e deixe o comando em execução em segundo plano.
    • 1) você precisa redirecionar stdoute stderrpara /dev/nullque eles não sejam redirecionados pelo terminal virtual que mantém a sessão SSH. Essa é a &>/dev/nullparte.
    • 2) você precisa redirecionar stdinpara um arquivo ilegível da mesma maneira. É isso que o shell interno nohupfaz.

Com apenas um comando em execução em segundo plano desanexado do terminal em todos os sentidos, exita sessão será encerrada e, como não existe stdinou ainda stdoutresta no terminal virtual, o SSH encerrará a conexão sem erros.

nachoparker
fonte
1

Eu uso o seguinte comando:

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

Aqui está o que isso está fazendo:

  • Ele instrui a máquina a reiniciar no próximo momento, mas não durante este comando
  • Sai corretamente do SSH
  • Mantém o SSH TTY o tempo todo, para que o sudo fique feliz e possa executar corretamente.
stieg
fonte
0

Você já tentou o seguinte

# shutdown -r now

Acho que em alguns sistemas em que trabalhei no passe, o comando reboot teve alguns problemas. Então, novamente, não consigo encontrar nada na página de manual do desligamento que faria o mesmo que reiniciar com o sinalizador -f.

Silverrocker
fonte
1
Sim, o desligamento não funciona na máquina na qual estou tentando conectar por alguns motivos estranhos. É por isso que eu uso reboot -f para forçar um desligamento e reiniciar.
coffemug
0

Que tal sair da sessão ssh e reiniciar o sistema usando o próximo comando:

ssh login@host "reboot -f"

Depois disso, pressione Ctrl + C para finalizar o ssh.

Renat Zaripov
fonte
0

Encontrei uma solução para isso que também pode ser útil para outras pessoas. Usei o seguinte comando para fechar a conexão logo após iniciar o comando anexado ao ssh:

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

Não entendo exatamente o motivo pelo qual esse comando força a conexão a fechar, mas pelo menos foi útil para mim. Se alguém entender por que mata a conexão ssh; Por favor explique.

coffeMug
fonte
0

Isso requer um atraso de 1 minuto, mas funcionou de maneira confiável para mim e resolve o problema do travamento do cliente SSH:

    $ sudo shutdown +1; logout

Isso programa o desligamento do sistema por 1 minuto depois, o que permite que o logout e, portanto, a finalização do SSH, sejam concluídos. Se você quiser esperar tão pouco tempo quanto possível, você poderia substituir o +1com HH:MMpor um tempo se aproximando rapidamente de dia, mas que pode ser complicado para o tempo corretamente e pode ter até um segundo atraso 59.

trpropst
fonte
0

Uma maneira simples que encontrei é comandar o desligamento / reinicialização como uma tarefa em segundo plano (usando '&'), protegendo-o de ser fechado quando a sessão fechar com 'nohup', juntamente com a saída imediata do shell / sessão:

nohup shutdown -r now & exit

Dessa forma, o cliente SSH não trava, pois a sessão é encerrada imediatamente, enquanto o sistema remoto continua com a reinicialização de forma assíncrona.

MikeW
fonte
Ou substituir o seu sistema de equivalente a "shutdown -r now" para uma reinicialização ....
MikeW
-2

Tente este comando:

$ reboot -f && exit
tH0r
fonte
2
Infelizmente isso não funciona.
coffemug
1
@AKh_Sw Seja específico para "não funciona".
gertvdijk
@AKh_Sw: se você digitar o sinal '$', ele não funcionará
tH0r 12/12/12
1
Sem utilidade. Isso é exatamente equivalente a reboot -f.
Gilles 'SO- stop be evil'