выход ожидает {} без тайм-аута

Я борюсь с классической проблемой ввода пароля автоматически в 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 без пароля" ответ. В то время как это - разумный совет, это не соответствующее решение в моем сценарии: Автоматическое тестирование ванили установило систему в доверяемой среде, где добавление доверенных ключей к изображению не желательно / возможный.

8
задан Kara 13 January 2014 в 02:27
поделиться

3 ответа

Итак, я нашел перестановку, которая, похоже, работает -

Сначала мне нужен сценарий обертка , который сообщит, когда будет выполнено:

#!/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 }
}

Спасибо за Дугласа Лидера (проголосовало) и Гленна Джекмана (проголосовало) за полезный совет. Я с радостью отклоню этот ответ и приму любой более элегантный ответ, возможно, тот, который покончит со сценарием-оболочкой.

Спасибо всем за внимание.

2
ответ дан 5 December 2019 в 17:34
поделиться

Вы, вероятно, захотите:

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 завершится.

7
ответ дан 5 December 2019 в 17:34
поделиться

Этот цикл:

expect {
    "*yes/no*" { send "yes\r" ; exp_continue }
    "*assword:" { send "${password}\r" ; exp_continue }
}

Не может завершиться никаким способом, кроме тайм-аута или EOF; две совпадающие строки будут exp_continue , поэтому повторите цикл.

Уход на задний план означает в основном разветвление; родитель умирает, а ребенок продолжает соединение.

Лично я бы решил интерактивные элементы по-другому:

  1. Ключи хоста: либо подключитесь один раз вручную, либо вставьте ключ прямо в файл ssh known_hosts.
  2. Пароль: Я бы использовал аутентификацию с закрытым / открытым ключом. Либо используйте агент для хранения ключа, либо получите ключ без пароля.
1
ответ дан 5 December 2019 в 17:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: