Как ssh с массивами в Expect / Tcl? - PullRequest
0 голосов
/ 29 января 2019

Я могу успешно порождать сессию ssh, выполнять некоторые scp и выполнять bash-скрипт в Excpet / Tcl.Тем не менее, когда я пытаюсь подключиться к многопользовательским системам через цикл for и массивы, я получаю ошибку ssh: Could not resolve hostname $SOME_HOST: Temporary failure in name resolution.

Мне бы очень хотелось иметь возможность сделать это с помощью массивов, но по любой причине, Expect / Tcl имеет проблемы при попытке использовать массивы с ssh.

#arrays
array set userArray {
    0 $A_USERNAME
    1 $A_USERNAME
    2 $A_USERNAME
    3 $B_USERNAME
    4 $B_USERNAME
    5 $A_USERNAME
    6 $A_USERNAME
    7 $A_USERNAME
    8 $A_USERNAME
    9 $A_USERNAME
    10 $B_USERNAME
    #11 $B_USERNAME
}

array set hostArray {
    0 $A_HOST
    1 $B_HOST
    2 $C_HOST
    3 $D_HOST
    4 $E_HOST
    5 $F_HOST
    6 $H_HOST
    7 $I_HOST
    8 $J_HOST
    9 $K_HOST
    10 $L_HOST
    #11 $M_HOST
}

array set sshPasswordArray {
    0 "placeholder0"
    1 "placeholder1"
    2 "placeholder2"
    3 "placeholder3"
    4 "placeholder4"
    5 "placeholder5"
    6 "placeholder6"
    7 "placeholder7"
    8 "placeholder8"
    9 "placeholder9"
    10 "placeholder10"
    #11 "placeholder11"
}


#expect "$ " { send -- "cd /tmp/\r" }



#This loop will step through every system on a system sshing and then running $LINUX_HARDWARE_COLLECTION_FILE on said system. 
for { set index 0 } { $index < $NUM_SYSTEMS_IN_A_SYSTEM } { incr index } {
    puts "In loop: $index"
    spawn ssh -o StrictHostKeyChecking=no -l $userArray($index) $hostArray($index)
    expect "*?assword:" 
    send "$sshPasswordArray($index)\r"
    #do some stuff here including executing $LINUX_HARDWARE_COLLECTION_FILE...
}

Кто-нибудь знает, как можно успешно это сделать?Кажется, проблема в том, что Excpet / Tcl не хочет читать значения моих массивов.Для приведенного выше кода предположим, что A_USERNAME, B_USERNAME, различные хосты и пароли являются допустимыми строками.

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Массивы в Tcl - это ассоциативные массивы, которые отображают произвольную строку в строку.
Списки в Tcl являются численно индексированными массивами.

Вы также можете сделать это:

set hostArray [list $A_HOST     $B_HOST     $C_HOST     $D_HOST     $E_HOST     $F_HOST     $H_HOST     $I_HOST     $J_HOST     $K_HOST     $L_HOST     $M_HOST]
set userArray [list $A_USERNAME $A_USERNAME $A_USERNAME $B_USERNAME $B_USERNAME $A_USERNAME $A_USERNAME $A_USERNAME $A_USERNAME $A_USERNAME $B_USERNAME $B_USERNAME]
set sshPasswordArray {
    "placeholder0"
    "placeholder1"
    "placeholder2"
    "placeholder3"
    "placeholder4"
    "placeholder5"
    "placeholder6"
    "placeholder7"
    "placeholder8"
    "placeholder9"
    "placeholder10"
    "placeholder11"
}

Затем выполните итерацию

for { set index 0 } { $index < [llength $userArray] } { incr index } {
    puts "In loop: $index"
    spawn ssh -o StrictHostKeyChecking=no -l [lindex $userArray $index] [lindex $hostArray $index]
    expect "*?assword:" 
    send "[lindex $sshPasswordArray $index]\r"
    #do some stuff here including executing $LINUX_HARDWARE_COLLECTION_FILE...
}

или, что намного удобнее, с foreach

foreach  user $userArray  host $hostArray  sshPassword $sshPasswordArray {
    spawn ssh -o StrictHostKeyChecking=no -l $user $host
    expect "*?assword:" 
    send "$sshPassword\r"
    #do some stuff here including executing $LINUX_HARDWARE_COLLECTION_FILE...
}
0 голосов
/ 30 января 2019

Команда array set при таком использовании не заменяет переменные в этих определениях.Например, hostArray(0) имеет буквенные символы $A_HOST.Самый простой способ исправить это - использовать команду subst для последующей обработки значений перед использованием.

for { set index 0 } { $index < $NUM_SYSTEMS_IN_A_SYSTEM } { incr index } {
    puts "In loop: $index"
    spawn ssh -o StrictHostKeyChecking=no -l \
            [subst $userArray($index)] [subst $hostArray($index)]
    expect "*?assword:" 
    send "$sshPasswordArray($index)"
    #do some stuff here including executing $LINUX_HARDWARE_COLLECTION_FILE...
}

Кроме того, не забудьте поставить \r в конце sendпароль (для имитации нажатия клавиши Return ) и не забудьте close порожденный подпроцесс в конце цикла.(Обычно это не критично для 10 элементов, но существует довольно небольшое количество виртуальных терминалов, которые вы можете открыть сразу, включая все остальные их пользователи на вашем компьютере; рекомендуется держать число открытым сразу же маленькимнасколько это возможно.)


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

array set userArray [subst {
    0 $A_USERNAME
    1 $A_USERNAME
    ... ...
}]

Примечание: array set вообще не поддерживает формат комментариев.Вы сделали записи с ключом #11 в вашем примере ...

...