Назад | Перейти на главную страницу

возникает несколько проблем при создании скрипта для обновления имен хостов в файле / etc / hosts?

Я совершенно новичок в сценариях и, следовательно, мне нужна помощь, чтобы исправить это.

У нас около 3000 виртуальных машин и 450 физических серверов, которые являются серверами на базе Linux (некоторые из них - Ubuntu, начиная с 9.x, и некоторые из них - Susu, начиная с 8.X, и большинство из них - RHEL, начиная с 4.x до 7.4) на для всех из них мне нужно добавить несколько записей имени хоста с данными IP в соответствующие файлы / etc / hosts.

У меня разные пользователи на каждом сервере с полным доступом к sudoers, который я могу использовать Следовательно, я создал файл CSV с именем хоста, именем пользователя и форматом пароля. который содержит необходимые данные для входа в систему. Имя файла: hostname_logins.csv

Мне нужно загрузить файл (т.е. список имен хостов на каждый из этих серверов, а затем обновить те же данные в каждом из файлов хостов серверов.

Я буду запускать этот скрипт на одном сервере RHEL 6. (Все остальные хосты разрешаются с этого сервера и достижимы, я это уже подтвердил.)

следовательно, нужна помощь, чтобы исправить этот сценарий.

скрипт не уверен, что в нем не так, поскольку я новичок в скриптах:

#!/bin/bash

while read hostname_login user_name user_password
do
        scp -p ./hostname_list $user_name:$user_password@$hostname_login:/tmp
        ssh -eS $user_name:$user_password@$hostname_login [bash -c "echo rishee | sudo -S mv /tmp/hostname_list ./hostname_list && cp -p /etc/hosts /etc/hosts.bkp && cat ./hostname_list >> /etc/hosts && rm -f ./hostname_list"]
done < hostname_logins.csv

Мне нужно сделать это как один скрипт, который будет работать на всех этих серверах. заранее спасибо.

Я не пробовал читать CSV в оболочке, так что это будет неполный ответ. Я обычно использую Perl или AWK для таких вещей.

Первая проблема заключается в том, что оболочка использует пробел для разграничения полей в строке, поэтому вам придется вместо этого разбивать поля на «,» (запятую). Так

IFS=","
while read hostname_login....

однако, если это "настоящий" CSV, он может выглядеть так

"hostname_login",username,"userpass"

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

Я не знаком с синтаксисом [bash -c] в вашем ssh, поэтому не могу его комментировать. Вместо этого я бы предпочел использовать одинарные кавычки (').

Я думаю, вы можете пропустить шаг переноса / tmp / hostname_list в домашний каталог. Вы можете просто сделать

 ssh -eS $user_name:$user_password@$hostname_login [echo rishee | sudo -S cp -p /etc/hosts /etc/hosts.bkp && cat /tmp/hostname_list >> /etc/hosts && rm -f /tmp/hostname_list"]

Я обновлю свой ответ, как только определю, что это [] настоящая вещь. Я когда-либо использовал его только в контексте сопоставления с образцом и как псевдоним для теста в условных выражениях. (т.е. for filename in hostname[0-9]; do ... или if [ -n "$var" ]; then...)

Также будут проблемы с ssh + sudo, когда ssh не может выделить pty, а sudo подходит к этому. Мне бы пришлось поискать, но я чувствую, что мы решили это, изменив /etc/sudo.config или что-то в этом роде, что не так оптимально.

Как написано, вы также выполняете sudo только для этого исходного mv / tmp / hostname ./hostname.

Лично, поскольку содержимое вашего файла статично, я бы упростил весь материал escape-последовательностей, предварительно написав то, что вы хотите запустить на другом конце, и скопировав это:

cat > hostname_list_script.sh

#/bin/bash

if ! cp -p /etc/hosts /etc/hosts.bkp; then 
  echo "Failed to backup /etc/hosts"
  exit 1 
fi

cat <<EOM  >> /etc/hosts
^D
cat hostname_list >> hostname_list_script.sh
EOM
^D

Теперь файл, который вы копируете, имеет немного текста вверху, содержимое, которое вы хотите добавить, а затем текст внизу, т. Е.

[...]
fi

cat <<EOM >> /etc/hosts
10.90.70.5  hostname1
10.90.70.4  hostname2
10.90.70.6  hostname3
EOM

Тогда ваш основной скрипт может читать

#/bin/bash

IFS=","

while read hostname_login user_name user_password
do 
   scp -p ./hostname_list_script.sh $user_name:$user_password@$hostname_login:/tmp 
   echo sudo_password | ssh -t -eS $user_name:$user_password@$hostname_login '/usr/bin/sudo -S -s bash /tmp/hostname_list_script.sh'
done < hostname_logins.csv

Собственно, я вижу другую проблему. Я думаю, вам нужно изменить пароль, переданный sudo, в зависимости от логина:

 echo $user_password | ssh ....

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

CAVEAT EMPTOR: Я не тестировал вышеупомянутую проблему доступности pty, и не нужно ли цитировать bash script аргумент sudo. В моей голове это работает, но вам, возможно, придется повозиться с цитатой, чтобы понять это правильно. Мне не нужно было обновлять файл / etc / hosts, поэтому я не тестировал его.

Также, как упоминал Spiderice, может быть проще установить BIND (DNS Nameserver) на одну из ваших машин и просто выполнить сценарий, который добавляет IP-адрес этой машины в /etc/resolv.conf вместо добавления в / etc / hosts. Когда я впервые начал читать ваш вопрос, я подумал, не придется ли нам также участвовать в удалении хостов и дедупликации вашей записи в / etc / hosts. Интересно, может ли это стать следующим вопросом через несколько месяцев, когда некоторые из хостов, которые вы добавляете сегодня, исчезнут или будут переименованы.

Мое предложение о том, как заставить такую ​​вещь работать, будет разбито на части. Итак, сначала отладьте цикл while:

#!/bin/bash
while read hostname_login user_name user_password
do 
    echo "$hostname_login / $user_name / $user_password"
done  < hostname_logins.csv

затем возьмите 4 верхних строки из файла hostname_logins.csv и доработайте содержимое цикла while, сначала добавив копирование файла внутри цикла while. Далее из командной строки работайте над строкой выполнения ssh, идущей на один хост. Как только вы все это проработаете, вы затем вставите свою развитую строку в цикл while в скрипте. Протестируйте еще раз на своем тестовом наборе из 4 хостов, и как только вы убедитесь, что все это сработало, скормите ему свой полный список хостов.