Получение SSH для выполнения команды в фоновом режиме на целевой машине
Это следующий вопрос к Как вы используете SSH в shell-скрипт? вопрос. Если я хочу выполнить команду на удаленной машине, которая работает в фоновом режиме на этой машине, как я могу получить команду ssh для возврата? Когда я пытаюсь просто включить амперсанд (&) в конце команды, он просто зависает. Точная форма команды выглядит так:
ssh user@target "cd /some/directory; program-to-execute &"
какие идеи? Одна вещь, чтобы отметить, что логины к целевой машине всегда производят текстовый баннер и у меня есть SSH ключи настроены так, что пароль не требуется.
12 ответов:
У меня была эта проблема в программе, которую я написал год назад-оказывается, ответ довольно сложный. Вам нужно будет использовать nohup, а также перенаправление вывода, Как описано в Википедии artcle on команды nohup, скопировано здесь для вашего удобства.
nohuping фоновые задания для пример полезен при входе в систему через SSH, поскольку в фоновом режиме работы может привести к оболочка, чтобы повесить на выход из системы из-за гонки состояние [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-ad
чтобы перечислить сеансы экрана:
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-bd
чтобы перечислить сеансы экрана:
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.
это сработало для меня май раз:
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 / directory; program-to-execute &"
Я думаю, что это то, что вам нужно: Сначала вам нужно установить
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