Вариант использования этого скрипта: у меня есть разные серверы с разными ключами ssh. Я пытаюсь написать скрипт, поэтому при вызове он войдет на указанный сервер. Пример использования:
./ServerLogin.sh Server1
Я чувствую, что я довольно близко, но последняя часть ожидаемого взаимодействия сбивает меня с толку. Это упрощенная версия:
#!/bin/bash
ServerName = "$1"
case $ServerName in
"Server1") IP = "1.2.3.4" ; keyPath = "/path/to/key.pem" ; password = "password" ; break ;;
*) echo "Server not recognized" ; exit ;;
esac
/usr/bin/expect << EOD
spawn ssh -i $keyPath user@$IP
expect "*.pem': "
send "$password\r"
interact
EOD
Результатом этого является то, что он входит в систему и сразу же закрывается. Я хочу, чтобы сеанс оставался интерактивным.
Есть идеи?
Как и ожидалось, он входит в систему, достигает взаимодействия и закрывается, потому что сценарий выполнен. Я не хочу, чтобы сценарий заканчивался... interact: received eof from spawn_id exp0
Почему бы не использовать ssh-agent
и ssh-add
?
Я полагаю, потому что я недостаточно знаком с этими инструментами. Я нашел решение проблемы, поэтому я обновлю ответ ниже.
(или напишите все это в tcl/expect вместо того, чтобы смешивать и сопоставлять с оболочкой) - но в любом случае, похоже, что что-то заставляет сеанс ssh выйти. Добавление полного вывода отладки к вашему вопросу было бы полезно.
Взгляните на мой sexpect (Expect for Shells), который вы можете использовать для написания сценариев Expect только с кодом оболочки.
Поигравшись с ним еще немного, я нашел рабочее решение. В основном создайте сценарий ожидания и запустите его. Почему это работает именно так, а не в исходном вопросе, мне не понятно. Но это работает, и я буду использовать это в настоящее время. Спасибо всем за помощь!
Рабочее решение:
#!/bin/bash
ServerName = "$1"
case $ServerName in
"Server1") IP = "1.2.3.4" ; keyPath = "/path/to/key.pem" ; password = "password" ; break ;;
*) echo "Server not recognized" ; exit ;;
esac
function WriteExp {
echo "#!/usr/bin/expect"
echo "spawn ssh -i $keyPath ubuntu@$IP"
echo "expect \"*.pem': \""
echo "send \"$password\\r\""
echo "interact"
}
WriteExp > $ServerName.exp
chmod 755 $ServerName.exp
/usr/bin/expect $ServerName.exp
# Cleanup the evidence
rm $ServerName.exp
Проблема в expect << EOF
. С expect << EOF
ожидание стандартного ввода — это документ здесь, а не телетайп. Но команда interact
работает только тогда, когда ожидаемый стандартный ввод является tty. Ваш ответ - одно из решений. Другое решение — использовать expect -c
, если вы предпочитаете не использовать файл tmp.
expect -c "
spawn ssh -i $keyPath user@$IP
expect \"*.pem': \"
send \"$password\r\"
interact
"
Отличный! это объяснение, которое я искал! Я, вероятно, буду использовать это в будущем, потому что мой сценарий bash немного сложнее. Спасибо!
Использование только tcl/expect, а не гибрида shell и it, делает код намного чище, без каких-либо потенциальных проблем, связанных с интерполяцией переменных оболочки:
#!/usr/bin/expect -f
switch -- [lindex $argv 0] {
Server1 {
set IP 1.2.3.4
set keyPath /path/to/key.pem
set password "password"
}
default {
puts stderr "Server not recognized"
exit 1
}
}
spawn ssh -i $keyPath user@$IP
expect "*.pem': "
send "$password\r"
interact
Ах! Вчера я сделал операторы переключения Google в ожидании и не нашел хорошего примера. Я рад узнать, что это возможно в чистом ожидании.
expect -d /your/script.exp ...
и посмотреть, что происходит.