Вопрос или проблема
Я регулярно выполняю действия, перебирая список серверов для выполнения некоторых действий. Например:
for s in `cat servers.txt` ; do
echo; echo $s
ssh $s 'выполнить что-то'
done
Мне интересно (с точки зрения оболочки), есть ли более простой способ сделать это, чем cat servers.txt
Да, я знаю о таких инструментах, как mcollective, capistrano и т. д. – я часто делаю это для исправления проблем с mcollective 🙂
Мой быстрый и грязный вариант… файл servers.txt содержит ряд хостов или IP-адресов, по одному в строке.
#!/bin/bash
SERVER_LIST=/path/to/servers.txt
while read REMOTE_SERVER
do
ssh $REMOTE_SERVER "выполнить_что-то_интересное"
done < $SERVER_LIST
Я использую ClusterSSH.
Он открывает много маленьких оболочек, и вы можете вводить команды во все одновременно. Это действительно удобно, когда вы хотите выполнить одну и ту же команду на множестве серверов, но все равно видеть вывод.
Я использую это так: clusterssh $(~/get-servers.sh)
, но, очевидно, вы можете сделать что-то вроде clusterssh $(cat servers.txt)
Результат выглядит следующим образом:
Он также доступен как пакет Debian.
Пожалуйста, сделайте себе одолжение и используйте что-то, предназначенное для этой цели. Вы уже знаете о mcollective, но вы и я оба знаем, что ему нужна какая-то инфраструктура для работы. Как и puppet и chef.
clusterssh, parallel ssh и dancer shell – это небольшие простые улучшения над циклом оболочки. Им не требуется больше инфраструктуры.
Но есть также ansible, который позволяет делать это, но также писать переиспользуемые “плейбуки” с несколькими шагами. Для этого требуется установить Python помимо sshd, но на практике мне никогда не приходилось отдельно его устанавливать, он всегда был доступен.
Ansible – это единственная система управления конфигурацией, которую я пробовал, которая также хорошо работает как инструмент развертывания и оркестрации (puppet нуждается в mcollective и, возможно, capistrano/fabric для этого, …)
(Да, Puppet и Chef и все остальные могут работать без центральных серверов, но вам нужно устанавливать пакеты на управляемых хостах, что ansible не требует)
Вот как использовать xargs для параллелизации этих ssh-сессий:
cat servers.txt | xargs -IH -n1 -P0 ssh H 'некоторые команды для выполнения'
Вы также можете добавить параметры -n или -f к ssh, чтобы перенаправить stdin из /dev/null или переместить сессию на фон. Если вам нужно вводить пароль для каждого хоста, это не так уж поможет, но если вы используете ssh-ключи, это работает очень хорошо.
Чтобы выполнить простую задачу на широком круге серверов, не используя инструменты, предназначенные для этой цели, независимо от того, требуется ли предварительная инфраструктура или нет, вы можете использовать простой скрипт для оболочки под названием mussh
, распространяемый как пакет во многих дистрибутивах.
Вы можете вызвать его со списком хостов, списком команд, сохранить обе вещи в файлы и заняться множеством других опций, таких как интеграция ssh-agent
, поддержка прокси и т. д. Пожалуйста, ознакомьтесь с руководством для всех деталей.
Пример может быть так же прост:
$ mussh -H host_list.txt -C command_list.txt
Вы рассматривали использование parallel-ssh? https://code.google.com/p/parallel-ssh/
Я обычно возвращаюсь к его использованию, если/когда наша установка mco или puppet сломана. Это еще одна зависимость для управления, но это совершенно того стоит, если у вас есть большой парк серверов для управления – с дополнительным бонусом выбора, на сколько машин работать одновременно/параллельно, или даже делать одну за раз, как вы привыкли с bash.
Я восстановил свой ответ. Хотя не совсем понятно, что именно вы спрашиваете.
Существует проект под названием parallel SSH, который предоставляет параллельные версии ssh, scp и rsync.
Таким образом, преимущество в том, что вам не нужно делать никакой оболочки, вы просто предоставляете ему список серверов, на которых нужно выполнить команду, и он выполнит это параллельно.
Это отлично, если у вас есть длинный набор ssh-команд, так как он выполнит их все параллельно, что может значительно ускорить процесс.
Например:
parallel-ssh -h myhosts.txt "echo 'hello world'"
#!/bin/bash
SERVER_LIST=/path/to/servers.txt
while read REMOTE_SERVER
do
ssh $REMOTE_SERVER "выполнить_что-то_интересное"
done < $SERVER_LIST
что происходит, когда один из серверов отключен в этом коде?
Я использовал hss для запуска приложений на 25 удаленных компьютерах, но я только что столкнулся с одним, который был отключен, и тогда hss искал этот хост и никогда не переходил к следующему. Так что это не оптимально, если один из моих компьютеров отключен.
перейдет ли приведенный выше код к следующему хосту в списке серверов, если он натолкнется на отключённый? Или нужно внести корректировку в этот код для достижения этого?
Скопировано из Sarav AK на middlewareinventory и изменено ниже
#!/bin/bash
# Скрипт для подключения к списку серверов с одним и тем же именем пользователя и паролем
# и получения имени хоста, времени работы и запроса установленной версии ОС
# вам понадобятся имя пользователя и пароль для удаленных хостов
# для этого требуется установка sshpass на локальной машине
echo "Введите удаленное имя пользователя"
read rmtuname
echo "Введите удаленный пароль"
read -s rmtpasswrd
# чтение IP-адресов из предопределенного списка хостов
for server in `cat /full/path/to/serverlist.txt`
do
# Печать удаленного списка хостов
echo "Обработка хоста "$server
# Запись локального скрипта оболочки для временного использования и сохранение в текущем месте
cat << 'EOF' > ./TestScript.sh
#!/bin/bash
echo "Запуск в $0"
echo "на имени хоста = `hostname` и "
echo "в отметке времени = `date` за время работы `uptime`"
echo "для версии RedHat `cat /etc/redhat-release`"
echo "для базовой версии Debian `lsb_release -a`"
exit 0
EOF
chmod a+x TestScript.sh
# SCP - копирование файла скрипта из текущего местоположения в удаленное временное местоположение
sshpass -p$rmtpasswrd scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no TestScript.sh $rmtuname@$server:/tmp/TestScript.sh
# Ожидание 3 секунды
sleep 3
# SSH на удаленный сервер и выполнение команды [Вызов скрипта]
sshpass -p$rmtpasswrd ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $rmtuname@$server "/tmp/TestScript.sh"
done
… небольшой фрагмент результата/возврата с узла ubuntu выглядит так
......
Обработка хоста 10.0.0.99
Предупреждение: '10.0.0.99' (ED25519) был навсегда добавлен в список известных хостов.
Предупреждение: '10.0.0.99' (ED25519) был навсегда добавлен в список известных хостов.
Запуск в /tmp/TestScript.sh
на имени хоста = UBUNTU-HOST1 и
в отметке времени = Сб 25 Мар 14:47:57 UTC 2023 за время работы 14:47:57 up 15 days, 18:56, 1 user, load average: 0.28, 0.19, 0.18
cat: /etc/redhat-release: Нет такого файла или каталога
для версии RedHat
Нет доступных модулей LSB.
для базовой версии Debian ID дистрибьютора: Ubuntu
Описание: Ubuntu 22.04.1 LTS
Версия: 22.04
Кодовое имя: jammy
Обработка хоста 10.0.0.110
......
Ответ или решение
Эффективные методы перебора списка серверов
Ваша задача по перебору списка серверов для выполнения определенных действий, таких как запуск команд через SSH, может быть оптимизирована и упростить вашу работу. На первый взгляд, вы использовали подход с циклом for
и командой cat
. Хотя это работает, существует множество более эффективных и управляемых решений. В этом ответе мы подробно рассмотрим несколько альтернативных методов.
1. Использование конструкции while read
Ваш текущий подход включает выполнение cat servers.txt
, что можно заменить на конструкцию while read
. Этот метод позволяет непосредственно читать файл и снижает потребление ресурсов, не требуя дополнительной команды. Пример:
#!/bin/bash
SERVER_LIST=/path/to/servers.txt
while read -r REMOTE_SERVER; do
echo; echo "Обрабатываем сервер: $REMOTE_SERVER"
ssh "$REMOTE_SERVER" 'do_something'
done < "$SERVER_LIST"
Этот вариант будет продолжать перебор даже в случае сбоя подключения к одному из серверов, предотвращая зависание скрипта.
2. Использование xargs
для параллелизации
Для повышения производительности команд можно использовать xargs
, чтобы выполнять команды параллельно. Это значительно снизит общее время выполнения для множества серверов:
cat servers.txt | xargs -I {} -n1 -P0 ssh {} 'do_something'
Здесь -P0
указывает xargs
запускать столько процессов, сколько возможно, что особенно полезно для работы с большим количеством серверов.
3. Применение ClusterSSH
и parallel-ssh
Если ваша задача состоит в том, чтобы видеть вывод с нескольких серверов одновременно, рассмотрите использование ClusterSSH
. Этот инструмент открывает несколько терминалов для работы с несколькими серверами одновременно и позволяет видеть результаты всех команд в реальном времени. Команда может выглядеть следующим образом:
clusterssh $(cat servers.txt)
Для выполнения команд одновременно, не заходя в каждый сервер, можно использовать parallel-ssh
, который предоставляет возможность параллельного выполнения SSH команд на множествах серверов:
parallel-ssh -h servers.txt "do_something"
4. Использование Ansible
Ansible — это мощный инструмент управления конфигурацией, который позволяет не только выполнять команды на нескольких серверах, но и создавать сложные автоматизация через "playbooks". Ansible не требует установки агентов на целевых серверах, что облегчает его использование в разных средах.
Пример команды Ansible может выглядеть следующим образом:
ansible all -i servers.txt -m shell -a 'do_something'
5. Обработка ошибок и управление зависаниями
Важно учитывать, что при выполнении команд на большом количестве серверов может произойти сбой подключения. В зависимости от ваших требований, вы можете добавить обработку ошибок в ваш скрипт. Вот пример:
#!/bin/bash
SERVER_LIST=/path/to/servers.txt
while read -r REMOTE_SERVER; do
echo; echo "Обрабатываем сервер: $REMOTE_SERVER"
ssh "$REMOTE_SERVER" 'do_something' || {
echo "Ошибка при подключении к $REMOTE_SERVER"
continue
}
done < "$SERVER_LIST"
Этот код заблокирует сессию только в случае успешного подключения, а в случае сбоя просто перейдет к следующему серверу.
Заключение
Выбор правильного подхода к перебору списка серверов зависит от ваших конкретных потребностей. В зависимости от размера и сложности вашей инфраструктуры и задач, вы можете принять решение, основываясь на наилучшей методологии. Надеюсь, предоставленные решения помогут вам в повышении эффективности вашего рабочего процесса с серверами.