Проблемы при цикле по серии команд ssh-ed

1549
JMzance

У меня есть ряд серверных машин, на которых я хочу запустить одну и ту же команду. Каждая команда занимает несколько часов, и (хотя я запускаю команды с использованием nohup и настраиваю их для выполнения в фоновом режиме), мне приходится ждать завершения каждой из них до следующего запуска. Вот примерно как я это настроил:

На хост-машинах:

for i in ; do ssh RemoteMachine$ ./RunJobs.sh; done 

Где RunJobs.sh на каждой удаленной машине:

 source ~/.bash_profile cd AriadneMatching for file in FileDirectory/Input_*; do nohup ./Executable $ & done exit 

Кто-нибудь знает такой способ, что мне не нужно ждать окончания каждой работы до следующего запуска? Или, альтернативно, лучший способ сделать это, у меня есть ощущение, что я делаю это довольно неоптимально. Ура, Джек

1
может быть, попробуйте вставить где-нибудь амперсанд .. http://superuser.com/questions/177218/how-to-start-gui-linux-programs-from-the-command-line-but-separate-from-the-com the термин может быть фоновым процессом. Некоторые дополнительные идеи здесь могут быть актуальны. http://stackoverflow.com/questions/29142/getting-ssh-to-execute-a-command-in-the-background-on-target-machine barlop 11 лет назад 0
У меня уже есть это с фактическим выполнением работы, но вы думаете, возможно, строки './RunJobs.sh' должны иметь амперсанд после него тоже? JMzance 11 лет назад 0
Я очень не осведомлен об этом, и я не заметил, что вы уже сделали амперсанд. barlop 11 лет назад 0
`для меня в ; do nohup ssh RemoteMachine $ ./RunJobs.sh& done`. Это не очень надежно, но быстро и грязно, если это работает на вас. Blacklight Shining 11 лет назад 0

4 ответа на вопрос

2
nitro2k01

Во-первых, вы можете захотеть взглянуть на использование screenвместо того, nohupчтобы заставить сеанс пережить разрыв соединения. screenдает вам виртуальный терминал, к которому вы можете вернуться позже. Основное назначение - screen yourcommandвыполнить yourcommandи screen -DRавтоматически подключиться к существующему сеансу или создать новый, если такового не существует. Просто запуск экрана без аргумента также дает вам подсказку внутри «экрана», который вы можете использовать.

Во-вторых, вы можете заглянуть в GNU Parallel для параллельных заданий. Возможно, вы не захотите запускать больше процессов, чем у процессорных ядер, из-за уменьшения отдачи и перегрузки диска. Подходящей командой для вас может быть следующая команда, которая, опять же, вам придется запустить внутри экрана, чтобы он выдержал отключение.

ls FileDirectory/Input_* | parallel -j 8 --workdir $PWD ./Executable {}

Файлы, которые вы хотите обработать, перечислены и переданы по конвейеру, в parallelкотором указывается запустить 8 параллельных заданий и работать в текущем каталоге.

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

screen sh -c 'ls FileDirectory/Input_* | parallel -j 8 --workdir $PWD ./Executable {}'

или просто

screen ./runjob

где runjobсодержится:

#!/usr/bin/env bash ls FileDirectory/Input_* | parallel -j 8 --workdir $PWD ./Executable {} 
Спасибо, но параллель не установлена ​​ни на одной из машин (и у меня нет прав sudo!) JMzance 11 лет назад 0
Незначительное предложение: `find FileDirectory -name 'Input_ *' -print0 | параллель -0 -j 8 --workdir $ PWD ./Executable {} `будет немного безопаснее, чем` ls`. Cristian Ciupitu 11 лет назад 0
@JackMedley Пожалуйста, опишите подробно, если ваша причина не покрыта http://oletange.blogspot.dk/2013/04/why-not-install-gnu-parallel.html Ole Tange 11 лет назад 1
1
MariusMatutiae

Используйте экран на каждой машине. screen запускает команду (обычно оболочку), которую можно отсоединить от сеанса ssh, чтобы он продолжал выполнять задание, только что начатое внутри него; другими словами, работа, хотя она все еще выполняется, не будет прервана никаким прерыванием (не только kill -9), когда вы выйдете из системы.

Когда вы захотите, вы можете переподключиться через ssh и повторно присоединиться к отдельному сеансу с помощью команды

screen -r 

и это без проблем вернет вас в оставленную вами оболочку и покажет вам все стандартные результаты, которые вы пропустили за это время, если таковые имеются.

Таким образом, вам не нужно ничего ждать, и у вас нет опасно зависающих сессий ssh, которые, если случайно отключить, убьют вашу работу.

Экран в репо.

0
Cristian Ciupitu

Решение для локальной машины

На основе параллельного ssh

# pssh -P --par 2 --hosts RemoteMachines /opt/RunJobs.sh 

или же:

# pssh -i --par 2 --hosts RemoteMachines /opt/RunJobs.sh 

Объяснение параметров:

-P --print Display output as it arrives. This option is of limited usefulness because output from different hosts are interleaved.  -i --inline Display standard output and standard error as each host completes.  -p parallelism --par parallelism Use the given number as the maximum number of concurrent connections.  -h host_file --hosts host_file Read hosts from the given host_file. 

На основе ансибл

# ansible --forks 2 -i RemoteMachines '*' -m command -a /opt/RunJobs.sh 

Объяснение параметров:

-f NUM, --forks=NUM Level of parallelism. NUM is specified as an integer, the default is 5.  -i PATH, --inventory=PATH The PATH to the inventory hosts file, which defaults to /etc/ansible/hosts.  -m NAME, --module-name=NAME Execute the module called NAME.  -a 'ARGUMENTS', --args='ARGUMENTS' The ARGUMENTS to pass to the module. 

Команда модуль принимает имя команды, за которым следует список разделенных пробелами аргументов. Данная команда будет выполнена на всех выбранных узлах. Он не будет обрабатываться через оболочку, поэтому такие переменные, как $ HOME, и такие операции, как "<", ">", "|" и "&" не будут работать.

Вы можете прочитать больше в разделе Введение в специальные команды .

NB ansible не будет переключаться на следующую группу хостов, пока не будут выполнены все текущие хосты («вилки»), поэтому его параллелизм ниже, чем у pssh (возможно, есть способ увеличить его, но я этого не знаю) ,

RemoteMachines файл выглядит примерно так для обоих случаев:

root@maria-clone1.skynet.tld root@maria-clone2.skynet.tld root@maria-clone3.skynet.tld root@maria-clone4.skynet.tld 

Решение для удаленных машин

Перепишите RunJobs.sh примерно так:

find FileDirectory -name 'Input_*' -print0 | xargs -0 -P 2 -n 1 ./Executable 

Пояснение :

-0, --null Input items are terminated by a null character instead of by whitespace, and the quotes and backslash are not special (every character is taken literally). Disables the end of file string, which is treated like any other argument. Useful when input items might contain white space, quote marks, or backslashes. The GNU find -print0 option produces input suitable for this mode.  -P max-procs, --max-procs=max-procs Run up to max-procs processes at a time; the default is 1. If max-procs is 0, xargs will run as many processes as possible at a time. Use the -n option or the -L option with -P; otherwise chances are that only one exec will be done.  -n max-args, --max-args=max-args Use at most max-args arguments per command line. Fewer than max-args arguments will be used if the size (see the -s option) is exceeded, unless the -x option is given, in which case xargs will exit. 

nitro2k01 «s решение на основе GNU Parallel является более мощным, но, как вы можете видеть, GNU xargs не так уж плохо.

0
Cwissy

for i in ; do ssh RemoteMachine$ ./RunJobs.sh; done

try this

for i in ; do echo RemoteMachine$; done |xargs -I % -n 1 -P 10 ssh % "./RunJobs.sh" 

what that does is build a list of machine names and pipes the whole list to xargs. The arguments to xargs mean:

-I % replace the occurrence of % with the first argument

-n 1 use 1 argument per command line

-P 10 run 10 processes at a time

Похожие вопросы