Отримання ssh для виконання команди у фоновому режимі на цільовій машині


304

Це наступне запитання до того, як ви використовуєте ssh в сценарії оболонки? питання. Якщо я хочу виконати команду на віддаленій машині, яка працює у фоновому режимі на цій машині, як я можу отримати команду ssh для повернення? Коли я намагаюся просто включити ampersand (&) в кінці команди, вона просто зависає. Точна форма команди виглядає так:

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

Будь-які ідеї? Варто зазначити, що при вході в цільову машину завжди створюється текстовий банер, і у мене встановлені SSH- ключі, тому пароль не потрібен.

Відповіді:


315

У мене була ця проблема в програмі, яку я написав рік тому - виявляється, відповідь досить складна. Ви повинні будете використовувати поЬір, а також перенаправлення виведення, як описаний в вікіпедії artcle на поЬір , скопійоване тут для вашої зручності.

Недопущення фонових завдань, наприклад, корисно, коли ви входите через SSH, оскільки фонові завдання можуть спричинити зависання оболонки під час виходу через стан перегонів [2]. Цю проблему можна також подолати шляхом перенаправлення всіх трьох потоків вводу / виводу:

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

1
Ці файли створюються в поточному каталозі. Отже обмеження - це кількість вільного місця на перегородці. Звичайно, ви також можете переспрямувати /dev/null.
Френк Кустерс

2
Будь-які ідеї щодо фонового процесу після його завершення з проханням підказати? (як-от gpg --decrypt, який закінчив запитувати пароль)
isaaclw

Спроба запустити працівника на заднім плані за допомогою nohup, але це не спрацює .. :(
Infant Dev

1
Чи можете ви поясніть, що < /dev/nullозначає? Дякую.
Qian Chen

1
Також із статті вікіпедії про nohup: "Також зауважте, що закриваючий сеанс SSH не завжди надсилає сигнал HUP до залежних процесів. Серед іншого, це залежить від того, був виділений чи ні псевдотермінал." Тож як суворо ногуп може не завжди бути потрібним, вам краще довго тривати з ним, ніж без.
Джакс

254

Це був найчистіший спосіб зробити це для мене: -

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

Єдине, що працює після цього - це фактична команда на віддаленій машині


7
-nне потрібен, як -fмається на увазі-n
blissini

6
ssh -fзалишає процес ssh підключеним, просто фоновим. Рішення / dev / null дозволяють ssh швидко відключитися, що може бути кращим.
Бені Чернявський-Паскін

Це рішення також працює для надсилання команд через ssh до Syonology NAS
Stefan F

Мені потрібні результати "ls -l", щоб показати на моєму пульті, ця команда не виконує цього.
Сіддхарт

@Siddharth Потім переспрямуйте на якийсь іменований файл, а не / dev / null.
sherrellbc

29

Переадресація фд

Вихід повинен бути перенаправлений, за допомогою &>/dev/nullякого перенаправляє і stderr, і stdout в / dev / null, і є синонімом >/dev/null 2>/dev/nullабо >/dev/null 2>&1.

Парантези

Найкращий спосіб - використовувати sh -c '( ( command ) & )'там, де командою є що завгодно.

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

Нохуп Шелл

Ви також можете використовувати 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 ) & )"'

8
Я знаю, що це ваша дуже стара відповідь, але чи можете ви додати коментарі щодо того, чому спосіб в дужках є найкращим способом, яка (якщо така є) різниця додається nohup , і чому і коли ви використовуєте nice? Я думаю, що це багато що додасть до цієї відповіді.
Д-р К

Можливо, щоб частково відповісти на це: За допомогою nohup вам не потрібно додавати & до команди, яку потрібно запустити.
Кадоїз

21

Якщо ви не можете / не можете тримати з'єднання відкритим, ви можете використовувати екран , якщо у вас є права його встановити.

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-a 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, які ви можете спробувати.


3
як можна було б скористатися screenдля цього?
Quamis

18

Я просто хотів показати робочий приклад, який можна вирізати та вставити:

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

Дуже корисний. Дякую.
Майкл Мартінес

8

Найшвидший і найпростіший спосіб - скористатися командою 'at':

ssh user @ target "зараз -f /home/foo.sh"


2
Це було б чудовим загальним рішенням, якщо atаргументи командного рядка приймаються після закінчення часу, а не тільки з файлу.
Тайлер Колліер

3
Ви можете імітувати файл із <<<, як у: ssh user @ target "зараз -f <<< 'my_comnads'"
Ніко

6

Я думаю, вам доведеться поєднати пару цих відповідей, щоб отримати те, що ви хочете. Якщо ви використовуєте ногуп разом із крапкою з комою та загортаєте все в лапки, тоді ви отримуєте:

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.


5

Це працювало для мене, можливо:

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

2

Ви можете це зробити так ...

sudo /home/script.sh -opt1 > /tmp/script.out &

Ідеально, працює з сеансом PuTTY SSH. Я можу вийти, і сценарій продовжується на машині. Дякую.
Satria

1

Насправді, коли мені потрібно запустити команду на віддаленій машині, яка є складною, я люблю вводити команду в сценарій на машині призначення та просто запускати цей скрипт за допомогою ssh.

Наприклад:

# simple_script.sh (located on remote server)

#!/bin/bash

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

І тоді я просто запускаю цю команду на вихідній машині:

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

0

Я намагався зробити те саме, але з додатковою складністю, що намагався зробити це з Java. Тож на одній машині, що працює на Java, я намагався запустити сценарій на іншій машині, у фоновому режимі (з нохупом).

З командного рядка ось що працює: (можливо, вам не знадобиться "-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.

Щоб пробувати цю роботу, потрібно було трохи проб і помилок, але зараз, здається, працює добре.


0

Мені здалося досить зручним проведення віддаленого сеансу tmux, використовуючи такий tmux new -d <shell cmd>синтаксис:

ssh someone@elsewhere 'tmux new -d sleep 600'

Це запустить новий сеанс на elsewhereхості, а команда ssh на локальній машині повернеться до оболонки майже миттєво. Потім ви можете перенести ssh на віддалений хост і tmux attachна цей сеанс. Зауважте, що про місцевий біг tmux немає нічого, лише віддалений!

Крім того, якщо ви хочете, щоб ваш сеанс зберігався після того, як робота виконана, просто додайте панель запуску оболонок після вашої команди, але не забудьте долучитись до лапок:

ssh someone@elsewhere 'tmux new -d "~/myscript.sh; bash"'

0
YOUR-COMMAND &> YOUR-LOG.log &    

Для цього слід запустити команду і призначити ідентифікатор процесу, ви можете просто перехрестити -f YOUR-LOG.log, щоб побачити результати, записані до нього, як вони відбуваються. Ви можете будь-коли вийти із системи та процес триватиме


0

Ви можете це зробити без nohup:

ssh user@host 'myprogram >out.log 2>err.log &'

-2

Я думаю, що це те, що вам потрібно: Спочатку потрібно встановити 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

-3

Спочатку виконайте цю процедуру:

Увійдіть в систему A як користувач 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: 

Нарешті додайте новий відкритий ключ до b @ B: .ssh / санкціонований_кейли та введіть пароль b останній раз:

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

Відтепер ви можете увійти в B як b від A як без пароля:

a@A:~> ssh b@B

тоді це буде працювати без введення пароля

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


1
У запитанні йдеться про те, що дагорій уже встановив ключі, щоб не вимагати пароля, але він все ще висить
Макс Нанасі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.