Explicador de scripts Expect

Cole um script Expect e leia o que ele faria, comando por comando: o que inicia (spawn), o que espera, o que digita, quando passa o teclado a você. Depois, o diálogo que conduz e os achados: uma senha em texto claro, um timeout deixado no padrão ou infinito, um padrão que casa cedo demais, um send sem o retorno que o programa espera, um script que termina antes de o programa responder. Analisado com o motor Tcl 8.4, nunca executado; cada regra cita o manual expect(1).

Texto e utilitários
Experimente

O Tcl consegue lê-lo. 1 erro, 1 aviso, 4 notas.

11 linhas, 9 comandos. Inicia telnet. Timeout no primeiro expect: o padrão, 10 segundos. Nunca espera o programa terminar.

O diálogo

nºlinhaespera porentão digita
13login:admin\r
25Password:••••••••
37>terminal length 0\r
49>show running-config\r

Comando por comando

  1. 1#!/usr/bin/expect

    Roda sob /usr/bin/expect: a primeira linha nomeia o interpretador; para o Tcl é um comentário.

  2. 2spawn telnet 10.0.0.1

    Inicia telnet com 10.0.0.1 como processo atual. Daqui em diante, expect lê a saída dele e send digita nele.

  3. 3expect "login:"

    Espera a saída do programa casar: um padrão.

    • login:
  4. 4send "admin\r"

    Digita admin\r no programa, terminando com um retorno.

  5. 5expect "Password:"

    Espera a saída do programa casar: um padrão.

    • Password:
  6. 6send "Cisco123\r"

    Digita Cisco123\r no programa, terminando com um retorno.

  7. 7expect ">"

    Espera a saída do programa casar: um padrão.

    • >
  8. 8send "terminal length 0\r"

    Digita terminal length 0\r no programa, terminando com um retorno.

  9. 9expect ">"

    Espera a saída do programa casar: um padrão.

    • >
  10. 10send "show running-config\r"

    Digita show running-config\r no programa, terminando com um retorno.

O script, com as linhas marcadas

#!/usr/bin/expect
spawn telnet 10.0.0.1
expect "login:"
send "admin\r"
expect "Password:"
send "Cisco123\r"
expect ">"
send "terminal length 0\r"
expect ">"
send "show running-config\r"

Achados

  1. notaE2linha 3Timeout
    expect "login:"

    Nenhum timeout foi definido antes deste expect, então vale o padrão de 10 segundos (expect(1)). Logins lentos e comandos longos precisam de mais; diga o que quer com set timeout.

  2. notaE7linha 3Sem tratamento de timeout
    expect "login:"

    4 expects esperam por um padrão sem tratamento de timeout. Quando o padrão não chega a tempo, o expect(1) executa uma ação nula implícita: o expect retorna em silêncio e o script segue como se tivesse casado, digitando comandos para um programa que não está onde o script pensa. Acrescente um padrão timeout que avise e saia.

  3. erroE1linha 6Segredo em texto claro
    send "Cisco123\r"

    Um segredo digitado em texto claro: logo após um prompt de senha, o script envia ••••••••, escrito no arquivo. Quem puder ler o script lê a senha. Tome-a da linha de comando (lindex $argv), do ambiente ($env(NOME)) ou peça-a com stty -echo e expect_user.

  4. notaE3linha 7Padrão que casa cedo demais
    expect ">"

    Um padrão de um só caractere, >. Os padrões não são ancorados e casam em qualquer ponto da saída, então um banner ou uma linha anterior que contenha esse caractere encerra a espera antes da hora. Case mais do prompt e ancore uma regexp com $ (o expect(1) recomenda quando se pode descrever o fim da cadeia).

  5. notaE3linha 9Padrão que casa cedo demais
    expect ">"

    Um padrão de um só caractere, >. Os padrões não são ancorados e casam em qualquer ponto da saída, então um banner ou uma linha anterior que contenha esse caractere encerra a espera antes da hora. Case mais do prompt e ancore uma regexp com $ (o expect(1) recomenda quando se pode descrever o fim da cadeia).

  6. avisoE4linha 10Termina em um send
    send "show running-config\r"

    O último ato do script é um send. Quando o script termina, o Expect fecha as conexões com os processos iniciados (expect(1)); o que o programa imprimir em resposta nunca é lido, e o programa pode não ter terminado. Termine com expect eof, um expect pelo prompt final ou interact.

O explicador lê o texto do script e nunca o executa. Segue os corpos de expect, if, foreach, while, for, switch, catch e proc na ordem do fonte, por isso não sabe qual ramo uma execução toma, quantas vezes um loop roda ou se um procedimento chega a ser chamado. Padrões e cadeias que dependem de uma variável aparecem como escritos. Cada fato sobre o Expect vem do expect(1), citado em Fontes.

Endpoint da APIGEThttps://ronutz.com/api/v1/expect-script-explainerDocumentado, não servido. Abre a especificação.

Referências