Виконайте віддалені команди, повністю відірвавшись від ssh-з'єднання


48

У мене є 2 комп’ютери, localpcі remoteserver.

Мені потрібно localpcвиконати кілька команд remoteserver. Одне з речей, що потрібно зробити, це запустити резервний скрипт, який працює протягом декількох годин. Мені б хотілося, щоб команда про localpc«вогонь», а потім працювала повністю незалежно remoteserver, як localpcніколи не була в першу чергу.

Ось що я робив до цього часу:

remoteserver містить має сценарій:

/root/backup.sh

localpc планується запустити це:

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

Чи я роблю це правильно? Чи є кращий спосіб зробити це? Чи зіткнуться я з будь-якими проблемами, роблячи це таким чином?


stackoverflow.com/questions/19996089/… та stackoverflow.com/questions/29142/… надають ряд корисних підходів до цієї проблеми, не використовуючи екран / tmux тощо ...
Павло

Відповіді:


47

Напевно, ви повинні використовувати screenна віддаленому хості, щоб мати справжню відокремлену команду:

ssh root@remoteserver screen -d -m ./script

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

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

52

Близько, але не зовсім.

Незалежно від будь-якого терміналу

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

Вам потрібно закрити всі дескриптори файлів, які підключені до ssh-сокету, оскільки сеанс ssh не закриється до тих пір, поки якийсь віддалений процес відкриє сокет. Якщо ви не зацікавлені у вихідному сценарії (мабуть тому, що сам сценарій піклується про запис у файл журналу), перенаправляйте його на це /dev/null(але зауважте, що це приховає помилки, такі як неможливість запуску сценарію).

Використання nohupне має тут корисного ефекту. nohupвпорядковує програму, яку вона запускає, щоб не приймати сигнал HUP, якщо керуючий термінал програми зникає, але тут терміналу в першу чергу немає, тому нічого не збирається надсилати SIGHUP в процес із синього вигляду. Крім того, nohupпереадресовує стандартний вихід і стандартну помилку (але не стандартний вхід) до файлу, але тільки якщо вони підключені до терміналу, що, знову ж таки, вони не є.

Від'єднання від терміналу

 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$ 

Використовуйте nohupдля від'єднання сценарію від його керуючого терміналу, щоб він не отримував SIGHUP, коли термінал зникає. nohupтакож перенаправляє стандартний вихід та стандартну помилку сценарію до файлу, який називається, nohup.outякщо вони підключені до терміналу; Ви повинні самі подбати про стандартне введення даних.

Зберігання віддаленого терміналу

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

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

Пізніше ви можете знову підключитися до терміналу, де працює сценарій, викликавши screen -S backup -rdяк root на цій машині.

Автоматизація однієї віддаленої команди

Для трохи кращої безпеки не відкривайте прямі віддалені кореневі логіни занадто широко. Створіть спеціальну пару ключів і дайте їй вимушене командування /root/.ssh/authorized_keys. Вміст файлу відкритого ключа є AAAA…== wibble@example.com; додайте розділений комами список опцій, включаючи command="…"який вказує, що ключ можна використовувати лише для виконання цієї конкретної команди. Не забудьте зберегти параметри та ключ усіх у одному рядку.

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…== wibble@example.com

Я спробував першу перераховану вами команду. Це не фон у вікні, який виконав команду. Курсор просто сидить там і чекає завершення ... можливо, це помилка?
LVLAaron

Можливо, вам доведеться перенаправити stdin на / dev / null у віддаленій системі. Ось чому, ssh не існує.
KeithB

Я б додав -fможливість отримати ssh на "background" (тобто припинити, закрити з'єднання) на локальній стороні. Це буде працювати спільно з &. nohupв цьому випадку є необов’язковим, але ви можете скористатися ним setsid.
Олексій

@KeithB Перенаправлення stdin є частиною цього, але мені також потрібно перенаправити stdout і stderr: nohup цього не зробить, оскільки вони не термінали, і насправді nohup тут не корисний.
Жил "ТАК - перестань бути злим"

1
@erikbwork Зауважте, що я абсолютно не маю поняття про ці речі, але після обговорення та коментарів: Гілз не використовує опцію -t у своїх командах, тому жоден псевдотермінал не буде встановлений ні у клієнта, ні на сервері. сторона. Тому НУП не надсилатиметься.
Бінарус

12

Стандартний рецепт запуску віддаленої команди з віддаленого входу, як SSH, є наступним:

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

Якщо commandце скрипт оболонки, який піклується про вхід у сам файл, то ви можете змінити command.logйого /dev/null. Як тільки ви почнете це, вийдіть відразу.

Вам потрібно все на цій лінії.

nohup повідомляє оболонці не порушувати процес, якщо сеанс входу відключений.

</dev/null повідомляє ніколи не чекати введення

>command.log повідомляє йому надсилати будь-які повідомлення до цього названого файлу журналу

2>&1повідомляє йому, щоб надсилати будь-які повідомлення stderr в той самий файл журналу. У деяких випадках краще мати два файли, у другому - збирати повідомлення про помилки, а перший - збирати звичайні повідомлення про активність. Це може полегшити переконання, що все працювало правильно.

& каже йому від'єднати цей процес і запустити його у фоновому режимі як демон-процес.


10

Ця тема була дуже корисною, але моє рішення мало бути іншим.

Мені не подобається рішення на екрані, оскільки воно залишає екранний процес, який мені не потрібен. Переспрямовування та переривання використовуються так:

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

НЕ працювали для мене при використанні команди ssh.

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

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

Потім на своїй клієнтській машині я запускаю (не помічаю перенаправлення):

# ssh remotemachine "backupwrapper.sh"
#

Команда ssh негайно повертається, з'єднання припиняється і сценарій залишається запущеним.


6

Як каже Нілс , це ризик для безпеки, щоб дозволити root входити через ssh. І я раджу не виконувати будь-яку істотну роботу на машині без журналу. Якщо щось піде не так, ви хочете, щоб у вас були повідомлення про усунення несправностей. Є й інші відповіді, які показують, як це зробити. Але ось як я рекомендую виконати саме те, про що ви просили. Це все вбудовано в sh (1). Не потрібно екрану GNU (хоча я думаю, що це розумне рішення). Додайте цей рядок в вашу команду: >&- 2>&- <&- &. >&-означає близький виступ. 2>&-означає близький stderr. <&-означає близький stdin. &означає працювати у фоновому режимі, наприклад

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$

0

Вам слід увімкнути віддалену команду remoteserver. Так, як ви це зробите, буде ввімкнено команду ssh localpc.

Крім того, це погана ідея, щоб дозволити root-ssh.

Отже, встановіть remoteserver: Лінія судорів, яка виконуватиметься /root/backup.shяк root користувачем backup.

Ви можете створити цього користувача без "хорошого" пароля.

Поставте команду sudo /root/backup.sh &як команду ~backup/.ssh/authorized_keys- разом із відкритим ключем від localpc(хто запускає цей сценарій).


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