Я борюсь с классической проблемой ввода пароля автоматически в ssh, и как все другие, относительно кого я спотыкаюсь в темноте, ожидают. Наконец я починил сценарий такая работа:
#!/usr/bin/expect -f
# command line args
set user_at_host [lrange $argv 0 0]
set password [lrange $argv 1 1]
set timeout 1
# ssh command
spawn ssh -S ~/.ssh/tmp.$user_at_host -M -N -f $user_at_host
# deal with ssh prompts
expect {
"*yes/no*" { send "yes\r" ; exp_continue }
"*assword:" { send "$password\r" ; exp_continue }
}
Этот сценарий завершается только благодаря timeout 1
строка, без него он просто зависает и завершится только взаимодействием с пользователем (^C
).
Когда spawn
строка была прямой командой ssh, сценарий, завершенный сразу же, однако это не Ваш прямой ssh. Вещь, которая могла бы отличаться, -f
опция, которые заставляют его работать в фоновом режиме (но я попробовал сценарий без него напрасно).
Я считал это interact
или expect eof
мог бы помочь, но я не смог найти корректное колдовство, которое на самом деле сделает это.
Мой вопрос (я думаю), То, как сделать ожидать сценарий, та икра фоновый процесс, оконечный без тайм-аута?
Править: Я должен был ожидать (никакая предназначенная игра слов) "использование аутентификация SSH без пароля" ответ. В то время как это - разумный совет, это не соответствующее решение в моем сценарии: Автоматическое тестирование ванили установило систему в доверяемой среде, где добавление доверенных ключей к изображению не желательно / возможный.
Итак, я нашел перестановку, которая, похоже, работает -
Сначала мне нужен сценарий обертка
, который сообщит, когда будет выполнено:
#!/bin/bash
"$@"
echo "done"
Затем сценарий ожидания выглядит следующим образом:
#!/usr/bin/expect -f
set user_at_host [lrange $argv 0 0]
set password [lrange $argv 1 1]
# no need for timeout 1
set timeout 60
# use the wrapper
spawn wrapper ssh -S ~/.ssh/tmp.$user_at_host -M -N -f $user_at_host
expect {
"*yes/no*" { send "yes\r" ; exp_continue }
"*assword:" { send "$password\r" ; exp_continue }
# use the wrapper
"done" { exit }
}
Спасибо за Дугласа Лидера (проголосовало) и Гленна Джекмана (проголосовало) за полезный совет. Я с радостью отклоню этот ответ и приму любой более элегантный ответ, возможно, тот, который покончит со сценарием-оболочкой.
Спасибо всем за внимание.
Вы, вероятно, захотите:
expect {
"*yes/no*" { send "yes\r" ; exp_continue }
"*assword:" { send "${password}\r" }
}
expect $the_prompt
send "exit\r"
expect eof
ОБНОВЛЕНИЕ
Я пропустил, что вы отправляете команду через ssh. Я думаю, все, что вам нужно, это следующее:
spawn ssh a@b foo bar baz
expect {
"*yes/no*" { send "yes\r" ; exp_continue }
"*assword:" { send "${password}\r" }
eof
}
Вы нажмете eof
, когда команда foo
завершится.
Этот цикл:
expect {
"*yes/no*" { send "yes\r" ; exp_continue }
"*assword:" { send "${password}\r" ; exp_continue }
}
Не может завершиться никаким способом, кроме тайм-аута или EOF; две совпадающие строки будут exp_continue
, поэтому повторите цикл.
Уход на задний план означает в основном разветвление; родитель умирает, а ребенок продолжает соединение.
Лично я бы решил интерактивные элементы по-другому: