Что делать, если аналоги платные или не адаптированы под наши условия? Конечно, писать самому.
Условие:
- ~ 50 удаленных клиентских станций, работающих на Ubuntu Desktop (10.04-12.10).
Задача:
- Получение информации о доступности обновления пакетов, на удаленных клиентских станциях.
- Логирование версий пакетов доступных для обновления.
- Удаленное обновление одной/всех клиентских станций.
Варианты решения:
- Landscape – Отлично, но платно.
- Spacewalk – Только RHEL и ему подобные.
- Собственная разработка – этот вариант как раз для нас.
Поскольку мои знания ограничиваются одним языком программирования – bash, реализация будет выполнена именно на нем.
Что нам потребуется:
- ssh-server на клиентских станциях.
- Общий пользователь для администрирования.
- Linux сервер (программа expect должна быть установлена).
- Сетевая шара (я использовал nfs).
Как будет работать:
ssh adm@IP -> сбор нужной информации -> запись в лог на сервер -> exit.
Как выглядит на практике:
При запуске программы отображается информация о пользователях и доступных пакетах для обновления. Имеется возможность ручного управления через меню. P.s реальные имена и IP заменены в целях анонимности. Далее показан пример выполнения первого пункта:
Краткая информация о системе, список пакетов доступных для обновления.
Примеры лог файлов, которые создает программа можно скачать тут
Реализация:
/root/uuman – корневая папка программы.
../uuman/log – папка с лог файлами (она же сетевая шара).
../../log/.menu_log – скрытая папка с краткой информацией о удаленной машине.
#!/usr/bin/expect -f set IP $argv #Ождиаем каждую команду set timeout -1 spawn ssh adm@$IP #Ождидам запрос на сертификат expect -re "(yes/no)" #Отправляем YES send "yes\r" #Ожидаем запрос на пароль expect -re ":" send "YOU_PASSWORD\r" expect -re "\\$ $" #Обязательноо запросить sudo пароль send "sudo -K\r" expect -re "\\$ $" #Становимся root send "sudo su\r" expect -re "password for" send "YOU_SUDO_PASSWORD\r" expect -re "# $" #Устанавливеам необходимые пакеты(если используете samba шару замените пакет nfs-common на cifs-utils) send "apt-get install -y apt-show-versions nfs-common\r" expect -re "# $" send "exit\r" expect -re "\\$ $" exit 0
#!/usr/bin/expect -f set IP [lrange $argv 0 0] set USERN [lrange $argv 1 1] set DATES [exec date "+%Y.%m.%d/%H:%M:%S"] #Подключаемся по ssh (adm сменить на своего пользователя) spawn ssh adm@$IP #Ждем ответ консоли expect -re "Password:" #Отправляем пароль send "YOU_PASSWORD\r" #Ждем конец строки $ expect -re "\\$ $" #Требуем обязательно запросить пароль от sudo send "sudo -K\r" expect -re "\\$ $" #Становимся root send "sudo su\r" expect -re "password for" send "YOU_SUDO_PASSWORD\r" #Ждем конец строки # expect -re "# $" #Создаем временную папку, для монтирования шары send "mkdir -m 777 /tmp/share > /dev/null 2>&1\r" expect -re "# $" #Монтируем nfs шару (для samba строка будет выглядить иначе) send "mount.nfs 192.168.0.1:/root/uuman/log /tmp/share\r" expect -re "# $" #Дата в лог файл send "date > /tmp/share/$IP.log\r" expect -re "# $" #Версия ядра, битность системы в лог файл send "uname -a >> /tmp/share/$IP.log\r" expect -re "# $" #Имя пользовтаеля в лог send "echo Username:$USERN >> /tmp/share/$IP.log\r" expect -re "# $" #IP в лог send "echo IP:$IP >> /tmp/share/$IP.log\r" expect -re "# $" #Имя хоста в лог send "(echo -n Hostname:;hostname) >> /tmp/share/$IP.log\r" expect -re "# $" #Версия Ubuntu в лог send "(cat /etc/issue.net) >> /tmp/share/$IP.log\r" expect -re "# $" #Считаем количетсво достпуных пакетов для обновления и записываем в лог файл send "(echo -n Count of packages for update:;apt-show-versions -u | wc -l) >> /tmp/share/$IP.log\r" expect -re "# $" #Пустая строка send "echo >> /tmp/share/$IP.log\r" expect -re "# $" #Расширеный список пакетов для обновления в лог send "apt-show-versions -u | column -t >> /tmp/share/$IP.log\r" expect -re "# $" #Строка для конфигурации денамического меню (ИМЯ пользователя | IP | ubuntu_version | кол-во пакетов | дата запроса) send "(echo -n $USERN;echo -n ' |' $IP '| ';cat /etc/issue.net | sed 's/ /_/g';echo -n AvailableUpdates\:;apt-show-versions -u | wc -l ;echo -n $DATES) > /tmp/share/.menu_log/$IP.log\r" expect -re "# $" #Отмонтируем шару send "umount -f /tmp/share\r" expect -re "# $" #Очищаем историю root send "history -c\r" expect -re "# $" #выходим из root send "exit\r" expect -re "\\$ $" exit 0
#!/usr/bin/expect -f set IP [lrange $argv 0 0] set USERN [lrange $argv 1 1] set DATES [exec date "+%Y.%m.%d/%H:%M:%S"] #Ждем окончания каждой команды set timeout -1 spawn ssh adm@$IP expect -re "Password:" send "YOU_PASSWORD\r" expect -re "\\$ $" send "sudo -K\r" expect -re "\\$ $" send "sudo su\r" expect -re "password for" send "YOU_SUDO_PASSWORD\r" expect -re "# $" #Обновляем систему send "apt-get -y upgrade\r" expect -re "# $" #Собираем информацию в лог send "mkdir -m 777 /tmp/share > /dev/null 2>&1\r" expect -re "# $" send "mount.nfs 192.168.0.1:/root/uuman/log /tmp/share\r" expect -re "# $" send "date > /tmp/share/$IP.log\r" expect -re "# $" send "uname -a >> /tmp/share/$IP.log\r" expect -re "# $" send "echo IP:$IP >> /tmp/share/$IP.log\r" expect -re "# $" send "(echo -n Hostname:;hostname) >> /tmp/share/$IP.log\r" expect -re "# $" send "(cat /etc/issue.net) >> /tmp/share/$IP.log\r" expect -re "# $" send "(echo -n Count of packages for update:;apt-show-versions -u | wc -l) >> /tmp/share/$IP.log\r" expect -re "# $" send "echo >> /tmp/share/$IP.log\r" expect -re "# $" send "apt-show-versions -u | column -t >> /tmp/share/$IP.log\r" expect -re "# $" send "(echo -n $USERN;echo -n ' |' $IP '| ';cat /etc/issue.net | sed 's/ /_/g';echo -n AvailableUpdates\:;apt-show-versions -u | wc -l ;echo -n $DATES) > /tmp/share/.menu_log/$IP.log\r" expect -re "# $" send "umount /tmp/share\r" expect -re "# $" send "apt-get -y upgrade\r" expect -re "# $" send "history -c\r" expect -re "# $" send "exit\r" expect -re "\\$ $" exit 0
#!/bin/bash #Дата для логов DATE=`date "+%Y.%m.%d/%H:%M:%S"` #Папка лог файлов LOCAL="/root/uuman/log" #Рабочая папка скрипта WORKD="/root/uuman" #[\]Идикатор работы spinner() { local pid=$1 local delay=0.25 while [ $(ps -eo pid | grep $pid) ]; do for i in \| / - \\; do printf ' [%c]\b\b\b\b' $i sleep $delay done done printf '\b\b\b\b' } #Функция для обновления информации о хостах UPDATEA() { #2012_11_23 DATEFN=`date "+%Y_%m_%d"` #Задаем права на папку с логами. Данная строка используется для nfs chown -R nfsnobody:nfsnobody $LOCAL i=0 #Обрабатываем каждую строку файла cat $WORKD/ip.txt | while read line; do USERN=`echo $line` #Получаем IP из строки IP=`echo $line | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'` #Доступность хоста if ping -c 1 -s 1 -W 1 $IP > /dev/null 2>&1; then i=`expr $i + 1` #Для каждого хоста отдельный screen screen -A -m -d -S "upd$i" expect $WORKD/update $IP $USERN #Строка для начальной настройки хостов #screen -A -m -d -S "upd$i" expect $WORKD/setup $IP else #Если хост не доступен пишем в логи соответсующий вывод #Данные в лог ошибок echo "$DATE" >> $LOCAL/err.txt echo "$USERN - not connected" >> $LOCAL/err.txt echo >> $LOCAL/err.txt #Данные в общий лог echo "$DATE | $USERN - not connected" >> $LOCAL/upd.txt echo >> $LOCAL/upd.txt #Данные в лог текущей даты echo "$DATE | $USERN - not connected" >> $LOCAL/UPD-$DATEFN.txt echo >> $LOCAL/UPD-$DATEFN.txt #Если хост когда-либо был в сети, не ставить статус not connected в меню NT=`cat $LOCAL/.menu_log/$IP.log | grep "AvailableUpdates"` if [ -z "$NT" ]; then echo -n "$USERN | Unknown | NotConnected | $DATE" > $LOCAL/.menu_log/$IP.log fi fi done #Информация по хостам в общий лог ls $LOCAL | grep .log | while read TXT; do paste $LOCAL/$TXT >> $LOCAL/upd.txt echo >> $LOCAL/upd.txt #В лог на текущую дату paste $LOCAL/$TXT >> $LOCAL/UPD-$DATEFN.txt echo >> $LOCAL/UPD-$DATEFN.txt done } #Функция для обновления всех хостов PACKAGEA() { #2012_11_23 DATEFN=`date "+%Y_%m_%d"` #Задаем права на папку с логами. Данная строка используется для nfs chown -R nfsnobody:nfsnobody $LOCAL i=0 #Обрабатываем каждую строку файла cat $WORKD/ip.txt | while read line; do USERN=`echo $line` #Получаем IP из строки IP=`echo $line | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'` #Доступность хоста if ping -c 1 -s 1 -W 1 $IP > /dev/null 2>&1; then i=`expr $i + 1` #Для каждого хоста отдельный screen screen -A -m -d -S "upd$i" expect $WORKD/package $IP $USERN else #Если хост не доступен пишем в логи соответсующий вывод #Данные в лог ошибок echo "$DATE" >> $LOCAL/err.txt echo "$USERN - not connected" >> $LOCAL/err.txt echo >> $LOCAL/err.txt #Данные в общий лог echo "$DATE | $USERN - not connected" >> $LOCAL/upd.txt echo >> $LOCAL/upd.txt #Данные в лог текущей даты echo "$DATE | $USERN - not connected" >> $LOCAL/UPD-$DATEFN.txt echo >> $LOCAL/UPD-$DATEFN.txt #Если хост когда-либо был в сети, не ставить статус not connected в меню NT=`cat $LOCAL/.menu_log/$IP.log | grep "AvailableUpdates"` if [ -z "$NT" ]; then echo -n "$USERN | Unknown | NotConnected | $DATE" > $LOCAL/.menu_log/$IP.log fi fi done #Информация по хостам в общий лог ls $LOCAL | grep .log | while read TXT; do paste $LOCAL/$TXT >> $LOCAL/upd.txt echo >> $LOCAL/upd.txt #В лог на текущую дату paste $LOCAL/$TXT >> $LOCAL/UPD-$DATEFN.txt echo >> $LOCAL/UPD-$DATEFN.txt done } #Функция генерация общего мини-отчета по хостам (Меню) MAIN() { rm -rf $LOCAL/MENU.txt ls $LOCAL/.menu_log | grep .log | while read MENU; do #Все для красивого вывода (возврат строки и замена символов) TEXT=`paste -s -d '|' $LOCAL/.menu_log/$MENU | sed 's/|/ | /g;s/-/|/g'` echo $TEXT >> $LOCAL/MENU.txt done #Очистка экрана и табличный вывод файла clear && cat $LOCAL/MENU.txt | column -t } #Меню скрипта MENU() { echo echo "1.Get update-information for Ubuntu-host (by custom IP-address)" echo "2.Get update-information for all Ubuntu-hosts (uses file with IP-addresses)" echo "3.Update packages for Ubuntu-host (by custom IP-address)" echo "4.Update packages for all hosts (uses file with IP-addresses)" echo "5.View error-connection log" echo "6.Refresh" echo "7.Exit" read SELECT case $SELECT in 1) #Информация о конкретном IP echo -n "Enter IP:" read IP #Задаем права на папку с логами. Данная строка используется для nfs chown -R nfsnobody:nfsnobody $LOCAL #Доступен ли хост if ping -c 1 -s 1 -W 1 $IP > /dev/null 2>&1; then #Находим пользовтеля по IP и получаем его имя USERN=`cat $WORKD/ip.txt | grep "$IP" | sed 's/ .*//'` $WORKD/update $IP $USERN > /dev/null 2>&1 & spinner $! cat $LOCAL/$IP.log else #Уведомляем и записываем в лог ошибок echo "Computer is not online" echo "$DATE" >> $LOCAL/err.txt echo "$IP - not connected" >> $LOCAL/err.txt echo >> $LOCAL/err.txt fi MENU ;; 2) #Обновить информацию о всех хостах UPDATEA > /dev/null 2>&1 & spinner $! #Не все хосты успевают быстро обработать информацию, можно выставить задержку перед показом меню #sleep 5s MAIN MENU ;; 3) #Обновить конкретный IP echo "Enter IP:" read IP #Задаем права на папку с логами. Данная строка используется для nfs chown -R nfsnobody:nfsnobody $LOCAL if ping -c 1 -s 1 -W 1 $IP > /dev/null 2>&1; then #Находим пользовтеля по IP и получаем его имя USERN=`cat $WORKD/ip.txt | grep "$IP" | sed 's/ .*//'` $WORKD/package $IP $USERN > /dev/null 2>&1 & spinner $! cat $LOCAL/$IP.log else echo "Computer is not online" echo "$DATE" >> $LOCAL/err.txt echo "$IP - not connected" >> $LOCAL/err.txt echo >> $LOCAL/err.txt fi MENU ;; 4) #Обновить все хосты PACKAGEA > /dev/null 2>&1 & spinner $! #Не все хосты успевают быстро обработать информацию, можно выставить задержку перед показом меню #sleep 5s MAIN MENU ;; 5) #Показать лог ошибок cat $LOCAL/err.txt MENU ;; 6) #Обновить MAIN MENU ;; 7) exit 0 ;; *) MENU esac } #Запуск скрипта с параметрами #Получаем параметр ARG=$1 case $ARG in #Обновить информацию о всех хостах check) UPDATEA exit 0 ;; #Обновить все хосты update) PACKAGEA exit 0 ;; *) MAIN MENU ;; esac
User2 — 192.168.0.2
User3 — 192.168.0.3
User4 — 192.168.0.4
Как пользоваться:
Если Вы использовали свои пути, поправьте следующие переменные в uuman.sh:
#Папка лог файлов LOCAL="/root/uuman/log" #Рабочая папка скрипта WORKD="/root/uuman"
Скрипт setup установит необходимые пакеты для работы программы на клиентских станциях. Чтобы использовать скрипт, в файле uuman.sh закомментируйте строку:
screen -A -m -d -S "upd$i" expect $WORKD/update $IP $USERN
И раскомментируйте:
#screen -A -m -d -S "upd$i" expect $WORKD/setup $IP
Автоматический режим:
$WORKD/uuman.sh check
— чек клиентских станций из файла ip.txt на доступность обновлений.
$WORKD/uuman.sh update
— обновление клиентских станций, доступных из файла ip.txt.
Итог:
Мы получаем клиент-серверную систему позволяющую в автоматическом или ручном режиме получать, хранить и обрабатывать информацию об актуальности установленных программ, пакетов безопасности и при необходимости производить обновление на клиентских станциях под управлением Ubuntu Linux.
ссылка на оригинал статьи http://habrahabr.ru/post/160579/
Добавить комментарий