Как использовать EXPECT в цикле для SSH

Вопрос или проблема

В нашей настройке Linux не настроен keygen для аутентификации без пароля. Поэтому я должен использовать только EXPECT для аутентификации без пароля в shell-скрипте.

   /usr/bin/expect<<EOF >> ${LOG_FILE}

set timeout 60
spawn   sftp ${EWS_USER}@${EWS_HOST}:${TGT_DIR}
expect "*?assword:"
send "$password\r"
expect "sftp>"
send "put $local_dir/$line\r"
expect "sftp>"
send "bye\r"
expect EOF
EOF

        filename=$(basename "$line")
        # echo "Имя файла: $filename"
        #Рассчитать MD5-сумму локально.
        local_md5sum=$(md5sum "$line")
        #echo "Локальная MD5-сумма: ${local_md5sum}"
        #Рассчитать MD5-сумму на удаленной машине
        remote_md5sum=$(ssh ${EWS_USER}@${EWS_HOST} "cd '$TGT_DIR' ; find -name '$filename'  -exec md5sum {} \;" < /dev/null)
        #echo "Удаленная MD5-сумма: ${remote_md5sum}"

LOCAL_SUM=`echo ${local_md5sum} | awk {'print $1'}`
REMOTE_SUM=`echo ${remote_md5sum} | awk {'print $1'}`
echo $LOCAL_SUM
echo $REMOTE_SUM
if [ "${LOCAL_SUM}" != "${REMOTE_SUM}" ]
then
        echo "SFTP успешно"
else
        echo "SFTP неуспешно"
fi

Я знаю, как использовать EXPECT в следующем сценарии:

sftp ${EWS_USER}@${EWS_HOST} << EOF >> ${LOG_NAME}
put ${LOCAL_DIR}/${line} ${TGT_DIR}/${line}
EOF

Но есть ли идеи, как использовать EXPECT в сценарии ниже, чтобы сделать соединение без пароля?

remote_md5sum=$(ssh ${EWS_USER}@${EWS_HOST} "cd '$TGT_DIR' ; find -name '$filename'  -exec md5sum {} \;" < /dev/null)

expect будет использоваться для ssh точно так же, как и для sftp, с самой сложной частью — как извлечь контрольную сумму из вывода. Это может выглядеть примерно так:

#!/usr/bin/env expect
#
# sftp на удаленный хост, затем контрольная сумма файла. предполагается наличие coreutils Linux
# на обоих концах

if {[llength $argv] == 0} {
    puts stderr "Использование: $argv0 somefiletoxfer"
    exit 64
}

set local_file [lindex $argv 0]
set local_sum [lindex [split [exec md5sum $local_file] " "] 0]
set file_basename [lindex [split $local_file "https://unix.stackexchange.com/"] end]

set match_max 9999    ;# в случае обильного вывода sftp или ssh
set timeout 60

# это также можно считать из $argv
set EWS_USER todofixme
set EWS_HOST todofixme
set TGT_DIR todofixme

set password hunter2

spawn sftp ${EWS_USER}@${EWS_HOST}:${TGT_DIR}
expect -ex "assword:"
send "$password\r"
expect -ex "sftp>"
send "put $local_file\r"
expect -ex "sftp>"
send "bye\r"
expect EOF

spawn ssh ${EWS_USER}@${EWS_HOST}
expect -ex "assword:"
send "$password\r"
send "md5sum ${TGT_DIR}/$file_basename\r"
expect -re {md5sum [^\n]+\n([A-Za-z0-9=_-]+) }
set remote_sum $expect_out(1,string)
send "exit\r"
expect EOF

if {$local_sum ne $remote_sum} {
    puts stderr "сбой вызывает это сообщение" 
    puts stderr "твои контрольные суммы не совпадают"
    puts stderr "локальная  >$local_sum<"
    puts stderr "удаленная >$remote_sum<"
    exit 1
}

puts $remote_sum
exit 0

Ответ или решение

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

expect — мощный инструмент, который позволяет автоматизировать взаимодействие с программами командной строки, ожидающими ввода от пользователя. Рассмотрим, как использовать данный инструмент для автоматизации ssh и sftp в контексте, описанном в вашем вопросе.

Обзор использования утилиты expect

  1. Установка контекста:

    • Удостоверьтесь, что expect установлен на вашей системе. В большинстве дистрибутивов Linux это можно сделать через пакетный менеджер: sudo apt-get install expect на Ubuntu или sudo yum install expect на CentOS.
  2. Автоматизация процесса SFTP:

    • Мы уже имеем пример, как с помощью expect выполнить загрузку файла через sftp:
      /usr/bin/expect <<EOF
      set timeout 60
      spawn sftp ${EWS_USER}@${EWS_HOST}:${TGT_DIR}
      expect "*?assword:"
      send "$password\r"
      expect "sftp>"
      send "put $local_dir/$line\r"
      expect "sftp>"
      send "bye\r"
      EOF
  3. Автоматизация проверки md5sum через SSH:

    • Для выполнения аналогичного подхода для выполнения команды ssh и проверки контрольной суммы файла:
      /usr/bin/expect <<EOF
      set timeout 60
      spawn ssh ${EWS_USER}@${EWS_HOST}
      expect "*?assword:"
      send "$password\r"
      expect "*$"
      send "cd '$TGT_DIR' && md5sum '$filename'\r"
      expect "*$"
      send "exit\r"
      EOF

Детали и пояснения

  • Установка таймаута: set timeout 60 устанавливает максимальное время ожидания в секундах. Это важно, чтобы команда не зависала в случае непредвиденных задержек.

  • Обработка ожидаемых событий: Команда expect следит за определёнными текстовыми последовательностями (например, "assword:") и реагирует на них. Это позволяет автоматически вводить данные, такие как пароль.

  • Завершение сеанса: Команды send "bye\r" и send "exit\r" корректно завершают сеансы sftp и ssh, закрывая соединения.

Дополнительные шаги

  • Отладка: Для отладки скрипта можно использовать флаг -d для expect, который выведет детальную информацию о выполняемых действиях. Это может помочь в случае, если что-то идёт не так.

  • Обработка ошибок: Необходимо предусмотреть обработку возможных ошибок, таких как неверный пароль или недоступность удалённого хоста.

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

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

Капча загружается...