Obtendo o ssh para executar um comando em segundo plano na máquina de destino

Esta é uma continuação da pergunta Como você usa o ssh em um shell script? questão. Se eu quiser executar um comando na máquina remota que é executada em segundo plano nessa máquina, como obtenho o comando ssh para retornar? Quando tento include apenas o e comercial (&) no final do comando, ele simplesmente trava. A forma exata do comando se parece com isso:

ssh user@target "cd /some/directory; program-to-execute &" 

Alguma ideia? Uma coisa a notar é que os logins para a máquina de destino sempre produzem um banner de texto e eu tenho as chaves SSH configuradas para que nenhuma senha seja necessária.

   

Eu tive esse problema em um programa que escrevi há um ano – a resposta é bastante complicada. Você precisará usar o nohup, bem como o redirecionamento de saída, conforme explicado no wikipedia artcle on nohup , copiado aqui para sua conveniência.

Nohuping jobs backgrounded é útil, por exemplo, quando logado via SSH, uma vez que jobs backgrounded podem fazer com que o shell permaneça no logout devido a uma condição de race [2]. Esse problema também pode ser superado redirecionando todos os três streams de E / S:

 nohup myprogram > foo.out 2> foo.err < /dev/null & 

Esta tem sido a maneira mais limpa de fazer isso por mim:

 ssh -n -f user@host "sh -c 'cd /whereever; nohup ./whatever > /dev/null 2>&1 &'" 

A única coisa que corre depois disso é o comando real na máquina remota

Redirecionar fd’s

A saída precisa ser redirecionada com &>/dev/null que redireciona stderr e stdout para / dev / null e é um sinônimo de >/dev/null 2>/dev/null ou >/dev/null 2>&1 .

Parantheses

A melhor maneira é usar sh -c '( ( command ) & )' onde o comando é qualquer coisa.

 ssh askapache 'sh -c "( ( nohup chown -R ask:ask /www/askapache.com &>/dev/null ) & )"' 

Shell Nohup

Você também pode usar o nohup diretamente para iniciar o shell:

 ssh askapache 'nohup sh -c "( ( chown -R ask:ask /www/askapache.com &>/dev/null ) & )"' 

Lançamento Agradável

Outro truque é usar bom para iniciar o comando / shell:

 ssh askapache 'nice -n 19 sh -c "( ( nohup chown -R ask:ask /www/askapache.com &>/dev/null ) & )"' 

Eu só queria mostrar um exemplo de trabalho que você pode cortar e colar:

 ssh REMOTE "sh -c \"(nohup sleep 30; touch nohup-exit) > /dev/null &\"" 

Se você não / não puder manter a conexão aberta, poderá usar a canvas se tiver o direito de instalá-la.

 user@localhost $ screen -t remote-command user@localhost $ ssh user@target # now inside of a screen session user@remotehost $ cd /some/directory; program-to-execute & 

Para desappend a session da canvas: ctrl-a d

Para listar sessões de canvas:

 screen -ls 

Para reativar uma session:

 screen -d -r remote-command 

Observe que a canvas também pode criar vários shells em cada session. Um efeito semelhante pode ser alcançado com o tmux .

 user@localhost $ tmux user@localhost $ ssh user@target # now inside of a tmux session user@remotehost $ cd /some/directory; program-to-execute & 

Para desappend a session do tmux: ctrl-b d

Para listar sessões de canvas:

 tmux list-sessions 

Para reativar uma session:

 tmux attach  

A chave de controle padrão do tmux, ‘ ctrl-b ‘, é um pouco difícil de usar, mas existem vários exemplos de configurações do tmux que são fornecidos com o tmux que você pode tentar.

Acho que você terá que combinar algumas dessas respostas para conseguir o que deseja. Se você usar nohup em conjunto com o ponto-e-vírgula e colocar a coisa toda entre aspas, você obtém:

 ssh user@target "cd /some/directory; nohup myprogram > foo.out 2> foo.err < /dev/null" 

o que parece funcionar para mim. Com nohup, você não precisa append o & ao comando para ser executado. Além disso, se você não precisa ler nenhuma das saídas do comando, você pode usar

 ssh user@target "cd /some/directory; nohup myprogram > /dev/null 2>&1" 

para redirect toda a saída para / dev / null.

A maneira mais rápida e fácil é usar o comando ‘at’:

ssh user @ target “agora -f /home/foo.sh”

Isso funcionou para mim pode vezes:

 ssh -x remoteServer "cd yourRemoteDir; ./yourRemoteScript.sh /dev/null 2>&1 & " 

Na verdade, sempre que preciso executar um comando em uma máquina remota que é complicado, gosto de colocar o comando em um script na máquina de destino e apenas executar esse script usando o ssh.

Por exemplo:

 # simple_script.sh (located on remote server) #!/bin/bash cat /var/log/messages | grep  | awk -F " " '{print $8}' 

E então eu apenas corro este comando na máquina de origem:

 ssh user@ip "/path/to/simple_script.sh" 

Eu estava tentando fazer a mesma coisa, mas com a complexidade adicional que eu estava tentando fazer de Java. Então, em uma máquina rodando java, eu estava tentando rodar um script em outra máquina, em segundo plano (com nohup).

A partir da linha de comando, eis o que funcionou: (você pode não precisar do “-i keyFile” se não precisar dele para o ssh no host)

 ssh -i keyFile user@host bash -c "\"nohup ./script arg1 arg2 > output.txt 2>&1 &\"" 

Note que para minha linha de comando, existe um argumento após o “-c”, que está entre aspas. Mas para ele funcionar do outro lado, ele ainda precisa das aspas, então eu tive que colocar citações de escape nele.

De java, aqui está o que funcionou:

 ProcessBuilder b = new ProcessBuilder("ssh", "-i", "keyFile", "bash", "-c", "\"nohup ./script arg1 arg2 > output.txt 2>&1 &\""); Process process = b.start(); // then read from process.getInputStream() and close it. 

Demorou um pouco de tentativa e erro para conseguir este trabalho, mas parece funcionar bem agora.

Primeiro siga este procedimento:

Faça o login em A como usuário a e gere um par de chaves de autenticação. Não insira uma frase secreta:

 a@A:~> ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/home/a/.ssh/id_rsa): Created directory '/home/a/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/a/.ssh/id_rsa. Your public key has been saved in /home/a/.ssh/id_rsa.pub. The key fingerprint is: 3e:4f:05:79:3a:9f:96:7c:3b:ad:e9:58:37:bc:37:e4 a@A 

Agora use o ssh para criar um diretório ~ / .ssh como usuário b em B. (O diretório pode já existir, o que é bom):

 a@A:~> ssh b@B mkdir -p .ssh b@B's password: 

Por fim, anexe a nova chave pública de a a b @ B: .ssh / authorized_keys e insira a senha de b uma última vez:

 a@A:~> cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys' b@B's password: 

A partir de agora você pode logar em B como b de A como sem senha:

 a@A:~> ssh b@B 

então isso funcionará sem digitar uma senha

ssh b @ B “cd / algum / diretório; programa para executar &”

Eu acho que isso é o que você precisa: Primeiro você precisa instalar o sshpass em sua máquina. então você pode escrever seu próprio script:

 while read pass port user ip; do sshpass -p$pass ssh -p $port $user@$ip <