Команда Linux expect с практическими примерами

LinuxLinuxBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этой лабораторной работе вы узнаете, как использовать команду Linux expect для автоматизации интерактивных приложений командной строки. Команда expect — это мощный инструмент автоматизации, который позволяет скриптам взаимодействовать с программами, требующими ввода данных пользователем, такими как SSH, FTP и другие интерактивные программы.

К концу этой лабораторной работы вы сможете:

  • Понимать назначение и базовый синтаксис команды expect
  • Создавать скрипты для автоматизации входа в систему SSH
  • Обрабатывать различные запросы и ответы в ваших скриптах expect

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

Шпаргалка по командам Linux

Понимание команды expect и ее базового синтаксиса

Команда expect в Linux позволяет автоматизировать интерактивные программы командной строки, которые обычно требуют ввода данных пользователем. Это особенно полезно для таких задач, как автоматический вход в систему, передача файлов или любая ситуация, когда программа запрашивает ввод.

Установка expect

Сначала давайте убедимся, что пакет expect установлен в нашей системе. Откройте терминал и выполните:

which expect

Если expect уже установлен, вы увидите его путь (например, /usr/bin/expect). Если нет, вам потребуется установить его:

sudo apt-get update
sudo apt-get install -y expect

Понимание базового синтаксиса expect

Команда expect использует язык сценариев, основанный на Tcl (Tool Command Language). Базовая структура скрипта expect включает следующие команды:

  1. spawn: Запускает процесс для взаимодействия
  2. expect: Ожидает определенный вывод от запущенного процесса
  3. send: Отправляет ввод запущенному процессу
  4. set timeout: Устанавливает время ожидания ожидаемого вывода

Давайте создадим простой скрипт expect, чтобы продемонстрировать эти концепции. Откройте текстовый редактор и создайте файл с именем hello.exp в вашем каталоге проекта:

cd ~/project
nano hello.exp

Введите следующее содержимое в файл:

#!/usr/bin/expect -f

## Set a timeout of 10 seconds
set timeout 10

## Spawn the bash process
spawn bash

## Wait for the bash prompt
expect "$ "

## Send a command to the bash process
send "echo Hello from expect\r"

## Wait for the bash prompt again
expect "$ "

## Exit the bash session
send "exit\r"

## Wait for the process to complete
expect eof

Сохраните файл, нажав Ctrl+O, затем Enter, и выйдите из nano с помощью Ctrl+X.

Сделайте скрипт исполняемым:

chmod +x ~/project/hello.exp

Теперь запустите скрипт:

~/project/hello.exp

Вы должны увидеть вывод, похожий на этот:

spawn bash
$ echo Hello from expect
Hello from expect
$ exit
exit

Понимание каждой строки скрипта

Позвольте мне объяснить, что делает каждая строка в скрипте:

  • #!/usr/bin/expect -f: Это строка shebang, которая указывает системе использовать интерпретатор expect для запуска этого скрипта.
  • set timeout 10: Это устанавливает таймаут в 10 секунд для любой команды expect, которая следует за ней.
  • spawn bash: Это запускает новый процесс оболочки bash, с которым будет взаимодействовать expect.
  • expect "$ ": Это ожидает появления приглашения bash.
  • send "echo Hello from expect\r": Это отправляет команду в оболочку bash. Обратите внимание на \r в конце, который имитирует нажатие клавиши Enter.
  • expect "$ ": Это снова ожидает приглашения bash после выполнения команды.
  • send "exit\r": Это отправляет команду exit для закрытия оболочки bash.
  • expect eof: Это ожидает завершения запущенного процесса.

Этот простой пример демонстрирует основную функциональность expect. В следующих шагах мы будем использовать эти концепции для создания более практичных скриптов.

Создание скрипта имитации входа в систему SSH с помощью expect

На этом этапе мы создадим скрипт expect, который имитирует процесс входа в систему SSH. Поскольку мы не можем выполнить фактический вход в систему SSH в этой среде, мы создадим имитационный скрипт, демонстрирующий принципы.

Понимание потока аутентификации SSH

При подключении к удаленному серверу через SSH типичное взаимодействие включает в себя:

  1. Инициирование соединения с помощью ssh username@hostname
  2. Принятие ключа хоста (если подключение выполняется впервые)
  3. Ввод пароля по запросу
  4. Получение доступа к удаленной оболочке

Давайте создадим имитационную среду SSH, чтобы продемонстрировать, как expect может автоматизировать этот процесс.

Создание скрипта имитации SSH-сервера

Сначала давайте создадим скрипт, который имитирует SSH-сервер, запрашивающий пароль:

cd ~/project
nano mock_ssh_server.sh

Введите следующее содержимое:

#!/bin/bash

echo "The authenticity of host 'mockserver' can't be established."
echo "RSA key fingerprint is SHA256:abcdefghijklmnopqrstuvwxyz123456."
echo "Are you sure you want to continue connecting (yes/no)? "
read answer

if [ "$answer" != "yes" ]; then
  echo "Host key verification failed."
  exit 1
fi

echo "Warning: Permanently added 'mockserver' (RSA) to the list of known hosts."
echo "Password: "
read -s password

if [ "$password" == "mockpassword" ]; then
  echo "Last login: Wed Nov 1 12:00:00 2023 from 192.168.1.100"
  echo "Welcome to Mock SSH Server"
  echo "mockuser@mockserver:~$ "

  while true; do
    read -p "" command
    if [ "$command" == "exit" ]; then
      echo "Connection to mockserver closed."
      exit 0
    else
      echo "Executing: $command"
      echo "mockuser@mockserver:~$ "
    fi
  done
else
  echo "Permission denied, please try again."
  exit 1
fi

Сохраните файл и сделайте его исполняемым:

chmod +x ~/project/mock_ssh_server.sh

Этот скрипт имитирует:

  • Запрос проверки хоста SSH
  • Запрос пароля
  • Простую оболочку, которая отвечает на команды

Создание скрипта expect для автоматизации входа в систему

Теперь давайте создадим скрипт expect, который автоматизирует взаимодействие с нашим имитационным SSH-сервером:

cd ~/project
nano ssh_login.exp

Введите следующее содержимое:

#!/usr/bin/expect -f

## Set variables
set timeout 10
set password "mockpassword"

## Start the mock SSH server
spawn ./mock_ssh_server.sh

## Handle the host verification prompt
expect "Are you sure you want to continue connecting (yes/no)? "
send "yes\r"

## Handle the password prompt
expect "Password: "
send "$password\r"

## Wait for the shell prompt
expect "mockuser@mockserver:~$ "

## Execute a command
send "ls -la\r"
expect "mockuser@mockserver:~$ "

## Exit the session
send "exit\r"

## Wait for the process to complete
expect eof

puts "\nSSH login automation completed successfully!"

Сохраните файл и сделайте его исполняемым:

chmod +x ~/project/ssh_login.exp

Запуск скрипта автоматического входа в систему

Теперь давайте запустим наш скрипт expect, чтобы автоматизировать взаимодействие с имитационным SSH-сервером:

cd ~/project
./ssh_login.exp

Вы должны увидеть вывод, похожий на этот:

spawn ./mock_ssh_server.sh
The authenticity of host 'mockserver' can't be established.
RSA key fingerprint is SHA256:abcdefghijklmnopqrstuvwxyz123456.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'mockserver' (RSA) to the list of known hosts.
Password:
Last login: Wed Nov 1 12:00:00 2023 from 192.168.1.100
Welcome to Mock SSH Server
mockuser@mockserver:~$ ls -la
Executing: ls -la
mockuser@mockserver:~$ exit
Connection to mockserver closed.

SSH login automation completed successfully!

Объяснение скрипта

Позвольте мне объяснить, что делает каждая часть нашего скрипта expect:

  1. set timeout 10: Устанавливает глобальный таймаут в 10 секунд для всех команд expect.
  2. set password "mockpassword": Сохраняет пароль в переменной.
  3. spawn ./mock_ssh_server.sh: Запускает наш скрипт имитации SSH-сервера.
  4. expect "Are you sure you want to continue connecting (yes/no)? ": Ожидает запроса проверки хоста.
  5. send "yes\r": Отправляет "yes", чтобы принять ключ хоста.
  6. expect "Password: ": Ожидает запроса пароля.
  7. send "$password\r": Отправляет пароль.
  8. expect "mockuser@mockserver:~$ ": Ожидает приглашения оболочки.
  9. send "ls -la\r": Отправляет команду для вывода списка файлов.
  10. expect "mockuser@mockserver:~$ ": Снова ожидает приглашения оболочки.
  11. send "exit\r": Отправляет команду exit для закрытия сеанса.
  12. expect eof: Ожидает завершения процесса.
  13. puts "\nSSH login automation completed successfully!": Выводит сообщение об успехе.

Этот пример демонстрирует, как expect можно использовать для автоматизации всего процесса входа в систему SSH, от принятия ключа хоста до выполнения команд на удаленном сервере и безопасного выхода.

Обработка нескольких запросов и ответов с помощью expect

В реальных сценариях интерактивные программы часто отображают несколько запросов и могут требовать разных ответов в зависимости от различных условий. На этом этапе мы узнаем, как обрабатывать несколько запросов и условные ответы в скриптах expect.

Понимание условных блоков expect

Команда expect может использоваться со структурой блок-действие для обработки различных возможных запросов:

expect {
    "pattern1" { actions for pattern1 }
    "pattern2" { actions for pattern2 }
    timeout { actions for timeout }
    eof { actions for end of file }
}

Эта структура позволяет вашему скрипту реагировать по-разному в зависимости от полученного вывода.

Создание скрипта обработки нескольких запросов

Давайте создадим скрипт, который имитирует программу с несколькими запросами:

cd ~/project
nano multi_prompt.sh

Введите следующее содержимое:

#!/bin/bash

echo "Please select an option:"
echo "1. Show date and time"
echo "2. List files"
echo "3. Show system info"
echo "4. Exit"
echo -n "Enter your choice (1-4): "
read choice

case $choice in
  1)
    echo "Current date and time:"
    date
    ;;
  2)
    echo "File listing:"
    ls -la
    ;;
  3)
    echo "System information:"
    uname -a
    ;;
  4)
    echo "Exiting program..."
    exit 0
    ;;
  *)
    echo "Invalid option. Please enter a number between 1 and 4."
    exit 1
    ;;
esac

echo "Do you want to continue? (yes/no): "
read answer

if [ "$answer" == "yes" ]; then
  echo "Continuing..."
  echo "Operation completed successfully."
else
  echo "Exiting program..."
fi

Сохраните файл и сделайте его исполняемым:

chmod +x ~/project/multi_prompt.sh

Теперь давайте создадим скрипт expect для взаимодействия с этой программой и обработки всех возможных запросов:

cd ~/project
nano handle_prompts.exp

Введите следующее содержимое:

#!/usr/bin/expect -f

## Set a timeout
set timeout 10

## Start the multi-prompt program
spawn ./multi_prompt.sh

## Wait for the choice prompt
expect "Enter your choice (1-4): "

## Generate a random choice (1-3)
set choice [expr {int(rand() * 3) + 1}]
send "$choice\r"

## Process the result based on the choice
switch $choice {
    1 {
        expect "Current date and time:"
        expect "Do you want to continue? (yes/no): "
    }
    2 {
        expect "File listing:"
        expect "Do you want to continue? (yes/no): "
    }
    3 {
        expect "System information:"
        expect "Do you want to continue? (yes/no): "
    }
}

## Handle the continue prompt
expect {
    "Do you want to continue? (yes/no): " {
        ## 70% chance to say yes, 30% chance to say no
        if {rand() < 0.7} {
            send "yes\r"
            expect "Operation completed successfully."
        } else {
            send "no\r"
            expect "Exiting program..."
        }
    }
    timeout {
        puts "Timeout waiting for continue prompt"
        exit 1
    }
}

## Wait for the program to complete
expect eof

puts "\nMulti-prompt handling completed successfully!"

Сохраните файл и сделайте его исполняемым:

chmod +x ~/project/handle_prompts.exp

Запуск скрипта обработки нескольких запросов

Теперь давайте запустим наш скрипт expect для взаимодействия с программой с несколькими запросами:

cd ~/project
./handle_prompts.exp

Каждый раз, когда вы запускаете этот скрипт, он случайным образом выбирает один из вариантов и случайным образом решает, продолжать или выйти. Вот пример вывода:

spawn ./multi_prompt.sh
Please select an option:
1. Show date and time
2. List files
3. Show system info
4. Exit
Enter your choice (1-4): 2
File listing:
total 20
drwxr-xr-x 2 labex labex 4096 Nov  1 10:00 .
drwxr-xr-x 4 labex labex 4096 Nov  1 10:00 ..
-rwxr-xr-x 1 labex labex  345 Nov  1 10:00 handle_prompts.exp
-rwxr-xr-x 1 labex labex  578 Nov  1 10:00 multi_prompt.sh
-rwxr-xr-x 1 labex labex  221 Nov  1 10:00 ssh_login.exp
Do you want to continue? (yes/no): yes
Continuing...
Operation completed successfully.

Multi-prompt handling completed successfully!

Создание более продвинутого скрипта expect

Теперь давайте создадим более продвинутый скрипт, который может обрабатывать непредвиденные запросы и ошибки:

cd ~/project
nano advanced_expect.exp

Введите следующее содержимое:

#!/usr/bin/expect -f

## Set a timeout
set timeout 10

## Define variables
set program "./multi_prompt.sh"
set max_retries 3
set retry_count 0

## Define a procedure to handle errors
proc handle_error {} {
    global retry_count max_retries program
    incr retry_count

    if {$retry_count < $max_retries} {
        puts "\nRetrying... Attempt $retry_count of $max_retries"
        ## Start the program again
        spawn $program
        return 1
    } else {
        puts "\nMaximum retry attempts reached. Exiting."
        exit 1
    }
}

## Start the program
spawn $program

## Main interaction loop
while {$retry_count < $max_retries} {
    expect {
        "Enter your choice (1-4): " {
            send "1\r"  ## Always choose option 1 for deterministic behavior
        }
        "Invalid option" {
            puts "\nReceived invalid option message."
            if {[handle_error]} continue
        }
        "Current date and time:" {
            ## Successfully got date output
        }
        "Do you want to continue? (yes/no): " {
            send "yes\r"
        }
        "Operation completed successfully." {
            puts "\nAdvanced expect script completed successfully!"
            break
        }
        timeout {
            puts "\nTimeout occurred waiting for prompt."
            if {[handle_error]} continue
        }
        eof {
            puts "\nUnexpected end of file."
            if {[handle_error]} continue
        }
    }
}

## Wait for the program to complete
expect eof

Сохраните файл и сделайте его исполняемым:

chmod +x ~/project/advanced_expect.exp

Запустите расширенный скрипт:

cd ~/project
./advanced_expect.exp

Пример вывода:

spawn ./multi_prompt.sh
Please select an option:
1. Show date and time
2. List files
3. Show system info
4. Exit
Enter your choice (1-4): 1
Current date and time:
Wed Nov  1 10:00:00 UTC 2023
Do you want to continue? (yes/no): yes
Continuing...
Operation completed successfully.

Advanced expect script completed successfully!

Понимание расширенного скрипта

Этот расширенный скрипт демонстрирует несколько важных методов expect:

  1. Обработка ошибок: Он использует механизм повторных попыток для обработки ошибок или непредвиденных ответов.
  2. Процедуры: Он определяет пользовательскую процедуру под названием handle_error для многократной обработки ошибок.
  3. Управление потоком: Он использует цикл while для поддержания взаимодействия до успеха или максимального количества повторных попыток.
  4. Несколько шаблонов expect: Он обрабатывает несколько различных шаблонов и выполняет соответствующие действия для каждого.
  5. Порядок шаблонов: Порядок шаблонов в блоке expect имеет значение - более конкретные шаблоны должны идти перед более общими.

Эти методы можно применять для автоматизации сложных интерактивных программ, в которых поток может меняться или могут возникать ошибки.

Создание практических скриптов expect для общих задач

На этом этапе мы создадим практические скрипты expect для общих задач, которые системным администраторам часто необходимо автоматизировать. Мы сосредоточимся на операциях с файлами, взаимодействии с пользователями и мониторинге системы.

Автоматизация передачи файлов с помощью expect

Давайте создадим скрипт expect, который автоматизирует передачу файла с помощью команды scp. Поскольку мы не можем выполнить фактическую передачу файла в этой среде, мы будем ее имитировать:

cd ~/project
nano file_transfer.sh

Введите следующее содержимое, чтобы имитировать передачу файла, подобную SCP:

#!/bin/bash

echo "scp file transfer simulation"
echo "Source file: $1"
echo "Destination: $2"
echo "Password: "
read -s password

if [ "$password" == "transfer123" ]; then
  echo "Transferring file..."
  echo "0%"
  sleep 1
  echo "25%"
  sleep 1
  echo "50%"
  sleep 1
  echo "75%"
  sleep 1
  echo "100%"
  echo "File transfer completed successfully."
else
  echo "Authentication failed."
  exit 1
fi

Сохраните файл и сделайте его исполняемым:

chmod +x ~/project/file_transfer.sh

Теперь давайте создадим скрипт expect для автоматизации этой передачи файла:

cd ~/project
nano file_transfer.exp

Введите следующее содержимое:

#!/usr/bin/expect -f

## Set variables
set timeout 10
set source_file "local_file.txt"
set destination "user@remote:/path/to/destination/"
set password "transfer123"

## Create a dummy source file
spawn bash -c "echo 'This is a test file' > $source_file"
expect eof

## Start the file transfer simulation
spawn ./file_transfer.sh $source_file $destination

## Handle the password prompt
expect "Password: "
send "$password\r"

## Monitor the transfer progress
expect "0%"
puts "Transfer started..."

expect "25%"
puts "Transfer 1/4 complete..."

expect "50%"
puts "Transfer 1/2 complete..."

expect "75%"
puts "Transfer 3/4 complete..."

expect "100%"
puts "Transfer almost done..."

expect "File transfer completed successfully."
puts "File transfer automation completed!"

## Clean up the dummy file
spawn bash -c "rm $source_file"
expect eof

Сохраните файл и сделайте его исполняемым:

chmod +x ~/project/file_transfer.exp

Запустите скрипт автоматизации передачи файлов:

cd ~/project
./file_transfer.exp

Пример вывода:

spawn bash -c echo 'This is a test file' > local_file.txt
spawn ./file_transfer.sh local_file.txt user@remote:/path/to/destination/
scp file transfer simulation
Source file: local_file.txt
Destination: user@remote:/path/to/destination/
Password:
Transferring file...
0%
Transfer started...
25%
Transfer 1/4 complete...
50%
Transfer 1/2 complete...
75%
Transfer 3/4 complete...
100%
Transfer almost done...
File transfer completed successfully.
File transfer automation completed!
spawn bash -c rm local_file.txt

Автоматизация создания пользователей с помощью expect

Теперь давайте создадим скрипт expect, который автоматизирует создание пользователей. Опять же, мы будем имитировать этот процесс:

cd ~/project
nano create_user.sh

Введите следующее содержимое:

#!/bin/bash

echo "User creation utility"
echo "Please enter new username: "
read username

echo "Please enter password for $username: "
read -s password

echo "Please confirm password: "
read -s password_confirm

if [ "$password" != "$password_confirm" ]; then
  echo "Error: Passwords do not match."
  exit 1
fi

echo "Creating user $username..."
echo "User $username created successfully."
echo "Do you want to add this user to the sudo group? (yes/no): "
read sudo_choice

if [ "$sudo_choice" == "yes" ]; then
  echo "Adding $username to sudo group..."
  echo "User $username added to sudo group."
fi

echo "User setup completed."

Сохраните файл и сделайте его исполняемым:

chmod +x ~/project/create_user.sh

Теперь давайте создадим скрипт expect для автоматизации создания пользователей:

cd ~/project
nano create_user.exp

Введите следующее содержимое:

#!/usr/bin/expect -f

## Set variables
set timeout 10
set username "testuser"
set password "P@ssw0rd123"
set add_sudo "yes"

## Start the user creation utility
spawn ./create_user.sh

## Handle the username prompt
expect "Please enter new username: "
send "$username\r"

## Handle the password prompt
expect "Please enter password for $username: "
send "$password\r"

## Handle the password confirmation prompt
expect "Please confirm password: "
send "$password\r"

## Wait for the user creation confirmation
expect "User $username created successfully."

## Handle the sudo prompt
expect "Do you want to add this user to the sudo group? (yes/no): "
send "$add_sudo\r"

## If we chose to add to sudo, wait for confirmation
if {$add_sudo == "yes"} {
    expect "User $username added to sudo group."
}

## Wait for completion
expect "User setup completed."

puts "\nUser creation automation completed successfully!"

Сохраните файл и сделайте его исполняемым:

chmod +x ~/project/create_user.exp

Запустите скрипт автоматизации создания пользователей:

cd ~/project
./create_user.exp

Пример вывода:

spawn ./create_user.sh
User creation utility
Please enter new username:
testuser
Please enter password for testuser:
Please confirm password:
Creating user testuser...
User testuser created successfully.
Do you want to add this user to the sudo group? (yes/no):
yes
Adding testuser to sudo group...
User testuser added to sudo group.
User setup completed.

User creation automation completed successfully!

Понимание практических скриптов expect

Практические скрипты, которые мы создали, демонстрируют несколько важных концепций для реальной автоматизации:

  1. Последовательное взаимодействие: Оба скрипта следуют определенной последовательности запросов и ответов.
  2. Мониторинг прогресса: Скрипт передачи файлов отслеживает прогресс и предоставляет удобные обновления для пользователя.
  3. Условная логика: Скрипт создания пользователей использует условную логику для обработки опции sudo.
  4. Настройка и очистка среды: Скрипт передачи файлов создает и очищает тестовые файлы.

Эти методы можно применять для автоматизации многих общих задач администрирования системы, таких как:

  • Удаленное резервное копирование
  • Установка программного обеспечения
  • Настройка системы
  • Пакетные операции

Освоив expect, вы можете автоматизировать сложные интерактивные процессы, которые в противном случае потребовали бы ручного вмешательства, экономя время и снижая вероятность человеческих ошибок.

Резюме

В этой лабораторной работе вы узнали, как использовать команду expect в Linux для автоматизации интерактивных приложений командной строки. Вы получили практический опыт работы с:

  • Установкой и пониманием базового синтаксиса команды expect
  • Созданием скриптов для автоматизации входа в систему SSH и обработки различных запросов аутентификации
  • Обработкой нескольких запросов и ответов в скриптах expect
  • Созданием практических скриптов автоматизации для общих задач администрирования системы

Команда expect — это мощный инструмент для системных администраторов и разработчиков, которым необходимо автоматизировать интерактивные процессы. Используя expect, вы можете исключить необходимость ручного вмешательства в повторяющиеся задачи, экономя время и снижая риск человеческих ошибок.

Некоторые ключевые выводы из этой лабораторной работы:

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

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

Linux Commands Cheat Sheet