Получение SSH для выполнения команды в фоновом режиме на целевой машине

Это следующий вопрос к Как вы используете SSH в shell-скрипт? вопрос. Если я хочу выполнить команду на удаленной машине, которая работает в фоновом режиме на этой машине, как мне вернуть команду ssh? Когда я пытаюсь просто включить амперсанд (&) в конце команды, он просто зависает. Точная форма команды выглядит так:

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

какие идеи? Следует отметить, что логины для целевой машины всегда производят текстовый баннер и у меня SSH клавиши настроены так, что пароль не требуется.

12 ответов


У меня была эта проблема в программе, которую я написал год назад-оказывается, ответ довольно сложный. Вам нужно будет использовать nohup, а также перенаправление вывода, Как описано в Википедии artcle on nohup, скопировано здесь для вашего удобства.

Nohuping backgrounded задания для пример полезен при входе в систему через SSH, поскольку в фоновом режиме работы может привести к shell для зависания на выходе из системы из-за гонки состояние [2]. Эта проблема также может быть побежденным путем перенаправления всех трех Потоки ввода-вывода:

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

Это был самый чистый способ сделать это для меня:-

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

единственное, что работает после этого команду на удаленном компьютере


редирект ФД это

выход должен быть перенаправлен с &>/dev/null который перенаправляет stderr и stdout в /dev / null и является синонимом >/dev/null 2>/dev/null или >/dev/null 2>&1.

Parantheses

лучший способ-использовать sh -c '( ( command ) & )' где команда-это что угодно.

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

Nohup Shell

вы также можете использовать nohup непосредственно для запуска оболочки:

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

Хороший Старт

еще один трюк - использовать nice для запуска команда / оболочка:

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

Я просто хотел показать рабочий пример, который вы можете вырезать и вставить:

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

если вы не/не можете сохранить соединение открытым, вы можете использовать , если у вас есть права на его установку.

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 &

чтобы отсоединить сеанс экрана:сочетания клавиш CTRL-а d

список сеансов экрана:

screen -ls

для повторного подключения сеанса:

screen -d -r remote-command

обратите внимание, что экран также может создавать несколько оболочек в каждом сеансе. Аналогичного эффекта можно добиться с помощью tmux.

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

чтобы отсоединить сеанс tmux:ctrl-b d

список сеансов экрана:

tmux list-sessions

для повторного подключения сеанса:

tmux attach <session number>

клавиша управления tmux по умолчанию,'ctrl-b', несколько сложно использовать, но есть несколько примеров конфигураций tmux, которые поставляются с tmux, которые вы можете попробовать.


Я думаю, вам придется объединить пару этих ответов, чтобы получить то, что вы хотите. Если вы используете nohup в сочетании с точкой с запятой и обертываете все это в кавычки, то вы получаете:

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

который, кажется, работает для меня. С nohup вам не нужно добавлять & к команде для запуска. Кроме того, если вам не нужно читать какие-либо выходные данные команды, вы можете использовать

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

для перенаправления всех выходных данных в /dev / null.


самый быстрый и простой способ-использовать команду "at":

ssh user@target "в настоящее время-f /home/foo.sh"


это сработало для меня в мае раз:

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

На самом деле, когда мне нужно запустить команду на удаленной машине, это сложно, мне нравится помещать команду в скрипт на целевой машине и просто запускать этот скрипт с помощью ssh.

например:

# simple_script.sh (located on remote server)

#!/bin/bash

cat /var/log/messages | grep <some value> | awk -F " " '{print }'

и затем я просто запускаю эту команду на исходной машине:

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

Я пытался сделать то же самое, но с дополнительной сложностью, которую я пытался сделать с Java. Поэтому на одной машине с java я пытался запустить скрипт на другой машине, в фоновом режиме (с nohup).

из командной строки, Вот что сработало: (возможно, вам не нужен "-I keyFile", если вам не нужен ssh для хоста)

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

обратите внимание, что в моей командной строке есть один аргумент после "-c", который находится в кавычках. Но для этого работа на другом конце, ему все еще нужны цитаты, поэтому мне пришлось поместить в него экранированные цитаты.

из java, вот что сработало:

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.

потребовалось немного проб и ошибок, чтобы заставить это работать, но теперь это работает хорошо.


сначала выполните следующую процедуру:

войдите в систему как пользователь a и создайте пару ключей аутентификации. Не вводите парольную фразу:

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

теперь используйте ssh для создания каталога ~/.ssh как пользователь b на B. (каталог может уже существовать, что нормально):

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

наконец, добавьте новый открытый ключ a к b@B:.ssh / authorized_keys и введите пароль b в последний раз:

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

теперь вы можете войти в B как b из A как A без пароль:

a@A:~> ssh b@B

тогда это будет работать без ввода пароля

ssh b@B " cd / some / каталог; программа для выполнения &"


Я думаю, что это то, что вам нужно: Сначала вам нужно установить sshpass на своей машине. затем вы можете написать свой собственный скрипт:

while read pass port user ip; do
sshpass -p$pass ssh -p $port $user@$ip <<ENDSSH1
    COMMAND 1
    .
    .
    .
    COMMAND n
ENDSSH1
done <<____HERE
    PASS    PORT    USER    IP
      .      .       .       .
      .      .       .       .
      .      .       .       .
    PASS    PORT    USER    IP    
____HERE