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

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

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

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

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

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

следовательно, нужна помощь для исправления этого сценария.

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

#!/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

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

0
задан 17 October 2017 в 21:15
1 ответ

Я не пробовал читать 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"]

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

Также будет быть проблемами с 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 хостов, и как только вы убедитесь, что все прошло успешно, скормите ему свой полный список хостов.

3
ответ дан 4 December 2019 в 12:19

Теги

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