Почему мой ожидаемый скрипт только выводит команду, не запущенную? - PullRequest
0 голосов
/ 12 октября 2018

Итак, я пытаюсь автоматизировать некоторый процесс SSH.У меня есть ожидаемый код.Но мой ожидаемый код только выводит команду / выводит команду.На самом деле он не запускает команду.

#!/usr/bin/expect -f

set timeout 10
set usrnm "aaaaaa"
set pwd "pppppp"
set addr1 "xxx.cloud.xxx.com -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
set addr2 "xxx.xxxx.xxxx.com"

spawn ssh $usrnm@$addr1

expect {

    "(yes/no)?" {send "yes\r";exp_continue} 

    "password: " {send  "$pwd\r"}

}


expect "*#"
send "ssh $usrnm@$addr2\r"

expect {

    "(yes/no)?" {send "yes\r";exp_continue} 

    "password:" {send  "$pwd\r"}

}

expect "*#"

send "cd /tmp/myself/folder\r"

expect "*#"

send "./run_engine.sh test.py\r"

expect eof

#interact

Так что, если я сделаю

expect my_expect.exp

, он просто напечатает команду:

spawn ssh aaaaaa@xxx.cloud.xxx.com -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no (10s later) ssh aaaaa@xxx.xxxx.xxxx.com (10s later) cd /tmp/amz337/COAFALV (10s later) ./run_engine.sh test.py (exit)

Что не так с моим сценарием?

1 Ответ

0 голосов
/ 12 октября 2018

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

xxx.cloud.xxx.com -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no

пробелы и все.

Логически, не имеет смысла помещать опции ssh в переменную, которая содержит адрес.Могу я предложить:

set addr1 "xxx.cloud.xxx.com"
set addr2 "xxx.xxxx.xxxx.com"
set ssh_opts($addr1) {-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no}
set ssh_opts($addr2) {}

Тогда

spawn ssh {*}$ssh_opts($addr1) $usrnm@$addr1

Синтаксис {*} - это оператор Tcl "splat", который разбивает слово с пробелами на отдельные слова.См. https://tcl.tk/man/tcl8.6/TclCmd/Tcl.htm правило № 5.

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

send "ssh $ssh_opts($addr2) $usrnm@$addr2\r"

Возможно, вы захотите перехватить события тайм-аута и прервать выполнение сценария:

expect {
    timeout      {error "timed-out connecting to $addr1"}
    "(yes/no)?"  {send "yes\r"; exp_continue} 
    "password: " {send  "$pwd\r"}
}

В конце сценария, после завершения сценария run_engine, вы все еще подключены к addr2, поэтому expect eof фактически не будетобнаружить eof на порожденном процессе.Время ожидания истечет через 10 секунд, и ожидаемый процесс завершится.Для удобства вы должны:

send "./run_engine.sh test.py\r"
expect "*#"
send "exit\r"
# this prompt is from addr1
expect "*#"
send "exit\r"
# _now_ the spawned ssh process will end
expect eof

Если вы считаете, что сценарий run_engine займет больше 10 секунд, вы должны отрегулировать переменную тайм-аута перед отправкой этой команды.

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

exp_internal 1

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

...