Использование expect в bash скриптах


Expect - это оболочка предоставляющая возможность програмировать диалог с интерактивными програмами. Под интерактивными програмами подразумеваются приложения, которые требуют ввода дополнительной информации в ходе работы.

Тяжело объяснить без примера. О примерах использвания expect дальше и пойдет речь. Планируется сборная статья, которая будет пополнятся разнообразными примерами использования expect.

Есть два варианта, по аналогии с perl/python:

  1. Создать скрипт-файл и запустить его следующим образом:

    expect -f script.exp

  2. Выполнить expect с командами в виде параметров:

    expect -c ' что-то сделать\r'

"\r" в конце строки означает отправку команды (нажатие клавиши Enter).

Основная структура скрипта:

#!/usr/bin/expect
spawn #выполняемое приложение или команда
expect #определяет в ответ на какой вопрос нужно отправить следующие ланные
send #что отправить в ответ на предыдущий вопрос

Если Вы хотите передать в скрипт какие-то параметры и использовать их в работе воспользуйтесь директивой set:

set var1 [lindex $argv 0] #первый параметр передаваемый скрипту
set var2 [lindex $argv 1] #второй параметр передаваемый скрипту

Используйте interact в конце, если по завершению выполнения всех send'ов сесия должна оставаться активной. Удобно для автоматизации при работе с ssh.

Пример 1: SSH

Стандартному линуксовому ссш клиенту можно стравить имя пользователя и ipадрес сервера как аргуметы, но пароль ему нельзя передать. Следующие скрипт принимает в качестве аргументов имя пользователя и пароль, дальше подключается с ними к серверу 192.168.1.10 и выполняет там cat /etc/issue

#!/usr/bin/expect
log_file expect_log
set login [lindex $argv 0]
set pw [lindex $argv 1]

spawn ssh $login@192.168.1.10
expect "$login@192.168.1.10\'s password:"
send "$pw\r"
expect "$login@"
send "cat /etc/issue\r"

Выполнить его можно так:

expect -f script.exp user password

Второй вариант - запустить все прямо в bash:

expect -c 'spawn ssh user@192.168.1.10; expect "Password:" {send -- "password\r"}; expect "user@" {send "cat /etc/issue\r"};'

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

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

log_file expect_log

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

set timeout 86000

Пример 2: FTP

Допустим нужно загрузить содержимое 10-ти ftp серверов в один каталог на сервере. Представьте использование 10-ти комбинаций логинов, паролей и адрдресов в lftp. Представили? Страшно?

Я вышел из ситуации следующим образом:

1. Создал файл со следующим содержанием:

#!/bin/bash
expect -c 'set timeout 86000; spawn lftp '"$1"'; expect "Password:" {send -- "'"$2"'\r"}; expect ">" {send "mirror -c --parallel=10\r"}; expect "/>" {send "exit\r"};'

2. Дальше катнул, эхнул, седнул и авкушнул оригинальный файл и получил новый файл в котором первая колонка - пользователь@ip_сервера, вторая - пароль.

user1@server1 password1
user1@server2 password2
user1@server3 password3
...
user1@serverN passwordN

3. В bash запустил следующу команду:

i=1 && end=$(cat file.txt |wc -l) && while [ $i -le $end ];do cmd=$(sed -n "$i"p file.txt |awk '{print $1}'); pwd=$(sed -n "$i"p file.txt |awk '{print $2}'); bash get_src $cmd $pwd; let "i = $i + 1";done

С помощью rsync загружаем выбраные папки с сервера

На сервере с Plesk файлы сайтов лежат в папках /var/www/vhosts/имя_сайта/httpdocs.

У нас есть список сайтов:

  • web-сайт1.com
  • web-сайт2.com
  • web-сайт3.com
  • web-сайт4.com
  • web-сайт5.com
  • web-сайт6.com
  • web-сайт7.com
  • web-сайт8.com
  • web-сайт9.com

Нужно стянуть папки этих сайтов на новый сервер.

В подобных случаях я инициализирую в bash список с названием list:

list="web-сайт1.com
web-сайт2.com
web-сайт3.com
web-сайт4.com
web-сайт5.com
web-сайт6.com
web-сайт7.com
web-сайт8.com
web-сайт9.com"

Подсказка: Набираете сначала list=", потом делаете вставку из буфера обмена, потом закрываете список двойными кавычками "

Дальше цыклом for перебираю эллементы списка:

for f in $list;do
mkdir -p /var/www/vhosts/$f;
expect -c 'spawn rsync -Hogva root@ip_адрес:/var/www/vhosts/$f/httpdocs /var/www/vhosts/$f/; expect "password:" {send -- "пароль\r"};interact';
done

Share Button
(Visited 6 945 times, 9 visits today)

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Лимит времени истёк. Пожалуйста, перезагрузите CAPTCHA.