Executa comandos remotos, desanexando completamente da conexão ssh

45

Eu tenho 2 computadores, localpc e remoteserver .

Eu preciso de localpc para executar alguns comandos em remoteserver . Uma das coisas que precisa fazer é iniciar um script de backup que seja executado por várias horas. Eu gostaria que o comando em localpc fosse "disparado" e então estivesse rodando de forma totalmente independente em remoteserver , como localpc nunca esteve lá em primeiro lugar.

Isso foi o que eu fiz até agora:

remoteserver contains tem o script:

/root/backup.sh

localpc está agendado para executar isto:

ssh root@remoteserver 'nohup /root/backup.sh' &

Estou fazendo isso da maneira certa? Existe uma maneira melhor de fazer isso? Terei algum problema em fazer isso dessa maneira?

    
por LVLAaron 30.01.2012 / 20:18

7 respostas

45

Você provavelmente deve usar screen no host remoto, para ter um comando real separado:

ssh root@remoteserver screen -d -m ./script
    
por 31.01.2012 / 23:04
47

Fechar, mas não exatamente.

Independentemente de qualquer terminal

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

Você precisa fechar todos os descritores de arquivos que estão conectados ao soquete ssh, porque a sessão ssh não fechará enquanto algum processo remoto tiver o soquete aberto. Se você não estiver interessado na saída do script (presumivelmente porque o próprio script cuida de gravar em um arquivo de log), redirecione-o para /dev/null (mas observe que isso ocultará erros, como não conseguir iniciar o script) .

Usar nohup não tem efeito útil aqui. nohup organiza para o programa que ele roda para não receber um sinal HUP se o terminal de controle do programa desaparecer, mas aqui não há terminal em primeiro lugar, então nada vai enviar um SIGHUP para o processo fora do azul. Além disso, nohup redireciona a saída padrão e o erro padrão (mas não a entrada padrão) para um arquivo, mas somente se eles estiverem conectados a um terminal, o que, novamente, eles não são.

Desanexar de um terminal

 aaron@localpc$ ssh root@remoteserver
 root@remoteserver# nohup /root/backup.sh </dev/null &
 nohup: appending output to 'nohup.out'
 [1] 12345
 root@remoteserver# exit
 aaron@localpc$ 

Use nohup para separar o script de seu terminal de controle para que ele não receba um SIGHUP quando o terminal desaparece. nohup também redireciona a saída padrão e o erro padrão do script para um arquivo chamado nohup.out se eles estiverem conectados ao terminal; você precisa cuidar da entrada padrão.

Mantendo um terminal remoto

Se você quiser manter o comando em execução em um terminal remoto, mas não tê-lo anexado à sessão SSH, execute-o em um multiplexador de terminal, como Tela ou Tmux .

ssh root@remoteserver 'screen -S backup -d -m /root/backup.sh'

Mais tarde, você pode se reconectar ao terminal em que o script está sendo executado invocando screen -S backup -rd como root nessa máquina.

Automatizando um comando remoto

Para uma segurança um pouco melhor, não abra logins raiz remotos diretos muito amplamente. Crie um par de chaves para fins especiais e atribua a ele um comando forçado em /root/.ssh/authorized_keys . O conteúdo do arquivo de chave pública é AAAA…== [email protected] ; adicione uma lista separada por vírgulas de opções, incluindo command="…" , que especifica que a chave só pode ser usada para executar este comando específico. Certifique-se de manter as opções e a chave em uma única linha.

command="/root/backup.sh </dev/null >/dev/null 2>/dev/null &",no-port-forwarding,no-agent-forwarding,no-x11-forwarding,no-pty,no-user-rc AAAA…== [email protected]
    
por 31.01.2012 / 01:14
11

A receita padrão para executar um comando remoto a partir de um login remoto como o SSH é o seguinte:

nohup command </dev/null >command.log 2>&1 &

Se command for um script de shell que cuida do registro em um arquivo, você poderá alterar command.log para /dev/null . Depois de iniciar isso, faça o logoff imediatamente.

Você precisa de tudo nessa linha.

nohup diz ao shell para não perturbar o processo se a sessão de login for desconectada.

</dev/null diz para nunca esperar pela entrada

>command.log diz para enviar qualquer mensagem para este arquivo de log nomeado

2>&1 diz para enviar quaisquer mensagens stderr para o mesmo arquivo de log. Em alguns casos, é melhor ter dois arquivos, o segundo para coletar mensagens de erro e o primeiro para coletar mensagens de atividade normais. Isso pode facilitar a verificação de que tudo funcionou corretamente.

& diz para desanexar este processo e executá-lo em segundo plano como um processo daemon.

    
por 01.02.2012 / 08:46
10

Este tópico foi muito útil, mas minha solução teve que ser um pouco diferente.

Não gosto da solução de tela porque deixa um processo de tela em execução que não preciso. Os redirecionamentos e nohups usados assim:

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

não estavam funcionando para mim quando usado com o comando ssh.

Eu criei um script de wrapper na máquina remota que executa o script real. O script wrapper define o redirecionamento e nohup. Algo parecido com isto:

backupwrapper.sh:
nohup backup.sh > /dev/null 2>&1 &

Em seguida, na minha máquina cliente, corro (não vejo redirecionamento):

# ssh remotemachine "backupwrapper.sh"
#

O comando ssh retorna imediatamente, a conexão é finalizada e o script fica em execução.

    
por 13.04.2012 / 20:56
6

Como Nils diz , é um risco de segurança permitir que o root faça o login via ssh. E eu aconselho contra a execução de qualquer trabalho substancial em uma máquina sem um log. Se algo der errado, você desejará ter algumas mensagens de solução de problemas. Existem outras respostas mostrando como fazer isso. Mas aqui está como eu recomendo realizar exatamente o que você pediu. Tudo é construído em sh (1). Não há necessidade de tela GNU (embora eu ache que é uma solução inteligente). Anexe esta cadeia ao seu comando: >&- 2>&- <&- & . >&- significa fechar stdout. 2>&- significa fechar stderr. <&- significa fechar stdin. & significa executar em segundo plano, por exemplo,

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$
    
por 14.08.2013 / 17:52
0

Você deve colocar em segundo plano o comando remoto em remoteserver . A maneira como você faz isso irá colocar em segundo plano o comando ssh em localpc .

Além disso, é uma má idéia permitir o root-ssh.

Portanto, configure em remoteserver : uma linha de sudoers que executará /root/backup.sh como raiz pelo usuário backup .

Você pode criar esse usuário sem uma senha "boa".

Coloque o comando sudo /root/backup.sh & as em ~backup/.ssh/authorized_keys - juntamente com a chave pública de localpc (quem acionar esse script).

    
por 30.01.2012 / 22:33
-1
#screen -d -m -S BACKUP ssh root@remoteserver /root/backup.sh
    
por 01.02.2012 / 10:06