2015-08-05 2 views
0

у меня есть список серверов в файле, который я прохожу к следующему сценарию:Выполнение последовательных команд через SSH на нескольких серверах

#!/bin/bash 

while IFS='' read -r line || [[ -n "$line" ]]; do 

    ssh_cmd="[email protected]$line" 
    ssh $ssh_cmd 'hostname && ls -l /path/to/folder | grep some_token' & 

done < "$1" 

То, что я хочу, выводимое так:

output from hostname (1) 
    output from ls -l (1) 
    output from hostname (2) 
    output from ls -l (2) 
    output from hostname (3) 
    output from ls -l (3) 

Но они, кажется, перепутаны:

output from ls -l (1) 
    output from hostname (1)  
    output from hostname (2) 
    output from ls -l (2) 
    output from ls -l (3) 
    output from hostname (3) 

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

Благодарим вас за консультацию!

ответ

1

& в конце этой линии делает это так, процесс выполняется в фоновом режиме:

ssh $ssh_cmd 'hostname && ls -l /path/to/folder | grep some_token' & 

Если удалить & из этой строки, скрипт будет ждать, пока SSH сессия не закончится, чтобы продолжить к следующей итерации цикла. Кроме того, вам нужно будет добавить флаг -n в команду ssh, чтобы он не читал из stdin. Это даст вам последовательный вывод, который вы ищете.

Final команды:

ssh -n $ssh_cmd 'hostname && ls -l /path/to/folder | grep some_token' 
+0

Спасибо. Когда я удаляю конечный '&', скрипт выполняется только для первого элемента в списке. Является ли 'ssh' каким-то образом остальным содержимым? –

+0

Причина, по которой моя петля не заканчивалась, заключалась в том, что ssh поглощал остальную часть потока stdin. Это были исправления, добавив флаг '-n' в мою команду' ssh': 'ssh -n user @ server command1 && command2' –

+1

@PatMustard Отлично! Извините, я не думал об этом, рад, что вы его исправили! Я отредактирую его в своем ответе будущим читателям. –

0

Используйте GNU Parallel, чтобы сделать их все красиво параллельно и использовать опцию -k сохранить вывод в порядке:

parallel -k -a hosts.txt 'echo ssh [email protected]{} "hostname; ls"' 

Итак, если hosts.txt содержит следующее:

host1 
host27 
host32 
host100 
hostfreddyfrog 
hostmichaelfish 

вы получите t его:

ssh [email protected] hostname; ls 
ssh [email protected] hostname; ls 
ssh [email protected] hostname; ls 
ssh [email protected] hostname; ls 
ssh [email protected] hostname; ls 
ssh [email protected] hostname; ls 

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

Еще одно преимущество, кроме того, что в настоящее время один вкладыш, является то, что если у вас есть 32000 хостов работать, GNU Parallel можно сказать, используя -j флаг, сколько процессов для запуска в то время без перегрузки сервера , По умолчанию, если у вас есть 8 ядер в вашем процессоре, он будет работать 8 рабочих мест параллельно, но вы можете установить его на 64, например, с

parallel -k -j 64 ... 

Вы также можете настроить GNU Parallel, чтобы иметь возможность ssh в хостах как правило, для распределения рабочих мест между серверами, тогда задача становится еще проще.

parallel -S node1,node4,node56 'hostname; grep ...' 

См example here.

АЛЬТЕРНАТИВА синтаксиса для прохождения hosts.txt является

parallel -k 'echo ssh [email protected]{} "hostname; ls"' < hosts.txt 

или

parallel -k 'echo ssh [email protected]{} "hostname; ls"' :::: hosts.txt 
Смежные вопросы