erro de manipulação em esperar?

5

Estou apenas melhorando a minha pergunta porque consegui até agora:

set username [lindex $argv 0]
set password [lindex $argv 1]
set hostname [lindex $argv 2]

if {[llength $argv] == 0} {
  send_user "Usage: scriptname username \'password\' hostname\n"
  exit 1
}

send_user "\n#####\n# $hostname\n#####\n"

spawn ssh -q -o StrictHostKeyChecking=no $username@$hostname

expect {
  timeout { send_user "\nFailed to get password prompt\n"; exit 1 }
  eof { send_user "\nSSH failure for $hostname\n"; exit 1 }
  "Password: "
}

send "$password\r"


expect {
  timeout { send_user "\nLogin failed. Password incorrect.\n"; exit 1}
  "{severname:mike} "
}
send "ls -lrt\n"

expect {
       "{severname:mike} " {
         send "uname\n"
       }
}
expect {
        "{severname:mike} " }

send "exit\r"
close

Espero que eu esteja correto, mas como faço para colocar os comandos logados localmente errlogs e success logs? onde comando é uma lista de comandos como ls, ls -lrt

Além disso, quando eu coloco isso:

 spawn ssh -q -o StrictHostKeyChecking=no $username@$hostname {ls -lrt;df -h}

ele efetua login e executa ls -lrt;df -h , mas depois disso, o erro erro com opção de depuração. A conexão fecha talvez por causa da execução do comando no escopo ssh.

[root@testgfs2 final]# ./workingscript.exp  mike bar01 10.38.164.103

#####
# 10.38.164.103
#####
spawn ssh -q -o StrictHostKeyChecking=no [email protected] ls -lrt
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {19901}

expect: does "" (spawn_id exp6) match glob pattern "Password: "? no
Password:
expect: does "Password: " (spawn_id exp6) match glob pattern "Password: "? yes
expect: set expect_out(0,string) "Password: "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "Password: "
send: sending "bar01\r" to { exp6 }

expect: does "" (spawn_id exp6) match glob pattern "{severname:mike} "? no


expect: does "\r\n" (spawn_id exp6) match glob pattern "{severname:mike} "? no
total 6
-rw-r--r--   1 mike   other        136 Feb 26 08:39 local.cshrc
-rw-r--r--   1 mike   other        157 Feb 26 08:39 local.login
-rw-r--r--   1 mike   other        174 Feb 26 08:39 local.profile

expect: does "\r\ntotal 6\r\n-rw-r--r--   1 mike   other        136 Feb 26 08:39 local.cshrc\r\n-rw-r--r--   1 mike   other        157 Feb 26 08:39 local.login\r\n-rw-r--r--   1 mike   other        174 Feb 26 08:39 local.profile\r\n" (spawn_id exp6) match glob pattern "{severname:mike} "? no
expect: read eof
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "\r\ntotal 6\r\n-rw-r--r--   1 mike   other        136 Feb 26 08:39 local.cshrc\r\n-rw-r--r--   1 mike   other        157 Feb 26 08:39 local.login\r\n-rw-r--r--   1 mike   other        174 Feb 26 08:39 local.profile\r\n"
write() failed to write anything - will sleep(1) and retry...
send: sending "ls -lrt\n" to { exp6 send: spawn id exp6 not open
    while executing
"send "ls -lrt\n""
    (file "./workingscript.exp" line 30)
A variável de comando

contém uma lista de comandos gerados por ponto-e-vírgula como este:

   command 1; command 2;command 3(=$command)

Eu não sei como posso executá-lo dentro de esperar script um por um então ao invés de colocar os comandos no escopo ssh Eu poderia fazer algo como:

spawn ssh -q -o StrictHostKeyChecking=no $username@$hostname

IFS=';'
for i in $command
do
expect {
   "{severname:mike} " {
           send "$i\n"
           }  2>> errorlog 1>> succeslog
    }
done

Acabei de usar a sintaxe unix e espero que a sintaxe seja combinada apenas para fazer você entender o que estou tentando fazer.

    
por munish 01.03.2013 / 09:41

1 resposta

7

O modelo de interação esperado não inclui uma separação de fluxos stdout e stderr. Quando você gera um processo, você cria um novo pseudo-TTY que se comporta quase de forma idêntica ao que um usuário veria em seu terminal, e um usuário normalmente não pode distinguir entre os dois. Experimente:

$ echo "This is stdout"
This is stdout
$ echo "This is stderr" 1>&2
This is stderr

Sem fazer alguma coisa para rotular a diferença, o Expect não pode distingui-las (assim como um usuário na linha de comando). Então, a Espera pode ser a ferramenta errada para o que você precisa fazer.

Agora, sem saber exatamente por que você precisa disso, é difícil encontrar um método alternativo para você. Para o que você precisa, parece que você pode fazer isso com um único comando ssh:

ssh -q -o StrictHostKeyChecking=no $username@$hostname "ls -lrt; df -h" 1>>successlog 2>>errorlog

Para outra linguagem de script com suporte interno para gerar um processo filho e obter seus stdout e stderr separadamente, tente o Python e seu módulo de subprocesso.

import shlex
from subprocess import Popen, PIPE
cmd = Popen(shlex.split('ssh -q -o StrictHostKeyChecking=no $username@$hostname "ls -lrt; df -h"'), stdout=PIPE, stderr=PIPE)
cmd.wait() # Wait for the command to complete
success_output = cmd.stdout
error_output = cmd.stderr

Mas se você realmente, realmente quiser fazer isso em Espera, acho que a melhor abordagem pode ser verificar o valor de saída do último processo e gravar em seu arquivo de log de erros quando ele estiver diferente de zero. Veja um exemplo de algo assim:

spawn ssh -q -o StrictHostKeyChecking=no $username@$hostname
# Receive password prompt and send the password here...
expect {
    -ex $prompt { send "ls -lrt\r" }
    timeout {
        send_user "Everything is terrible forever.\n"
        exit 1
    }
}
expect {
    -ex $prompt {
        set output $expect_out(buffer)
        send {echo RETVAL::$?::}
        send "\r"
    }
    timeout {
        send_user "Everything is terrible forever.\n"
        exit 1
    }
}
expect {
    -ex {RETVAL::0::} {
        set fp [open successlog a]
        puts $fp $output
        close $fp
    }
    -re {RETVAL::[1-9][0-9]*::} {
        set fp [open errorlog a]
        puts $fp $output
        close $fp
    }
    timeout {
        send_user "Everything is terrible forever.\n"
        exit 1
    }
}
    
por 04.03.2013 / 21:40