[SP-pm] Perl para automação em acesso a x3270 IBM
Eden Cardim
edencardim at gmail.com
Mon Jul 9 13:59:55 PDT 2012
>>>>> "Marcio" == Marcio <- Google <marciorp em gmail.com>> writes:
Marcio> Preciso criar um programa para navegar (ler e inserir) em um sistema
Marcio> que roda em Mainframe IBM (x3270(9)).
Ai caramba... Lá vem pergunta difícil...
Marcio> Ele irá simular a interação humana, conecta no host, espera
Marcio> pela tela, insere dados em determinadas posições e submete
Marcio> para o host, etc. Se usar Perl com Windows é moleza com o
Marcio> módulo Win32::HostExplorer, o problema é que estou usando
Marcio> Linux em modo texto, nada de ambiente gráfico. Não achei
Marcio> uma versão do Win32::HostExplorer para Linux, mais achei o
Marcio> http://x3270.bgp.nu/, mais especificamente o s3270. Instalei
Marcio> e compilei, rodei o módulo c3270 e funciona perfeito,
Marcio> conectou no host, montou as telas, entrou dados e tudo mais.
Marcio> Agora preciso usar o s3270 que é pelo que entendi o módulo
Marcio> para automação. Só que a documentação é muito fraca e
Marcio> encontrei meia dúzia de exemplos mais fracos ainda.
Não sei se você chegou a encontrar essas páginas, mas achei bem
completo:
http://x3270.bgp.nu/s3270-man.html
http://x3270.bgp.nu/x3270-script.html
Marcio> Até consegui fazer um script pequeno em Perl (usando um
Marcio> exemplo) que conecta no host, e faz alguma interação, mais
Marcio> agora esbarrei no conhecimento limitado de Perl.
Marcio> O que consegui fazer até agora é isso:
Marcio> <snip>
Marcio> O código funciona, pois a variável $out tem tudo o que foi processado
Marcio> (saída) e os dados (telas) estão certos.
Marcio> A dificuldade está no fato de que o script é processado como um todo
Marcio> quando chega à linha "finish $h or die "s3270 returned $?";" e a
Marcio> variável $out só é alimentada ai. A questão é que cada vez que eu
Marcio> entro dados eu preciso processar o retorno do host (ler a tela) para
Marcio> verificar se está tudo certo e ir para a próxima ação.
Marcio> Para ficar mais fácil de entender, a cada vez que eu mandar a
Marcio> instrução "Ascii(0,0,24,80)\n" preciso que a variável $out seja
Marcio> alimentada com tudo o retorno do host até essa ação, para que eu possa
Marcio> pegar os dados e ver se está tudo certo, depois disso limpar a
Marcio> variável e continuar até a próxima vez que eu precisar ler o retorno.
Marcio> Já tentei colocar o "finish ..." no meio e ler a variável de saída,
Marcio> mais depois do "finish ..." o script é encerrado, independente de eu
Marcio> enviar as instruções “disconnect” ou “quit”.
Marcio> A variável de retorno tem as telas que o host retorna (não tem tamanho
Marcio> fixo), então tenho que sair garimpando no meio os dados que preciso
Marcio> para saber qual a próxima ação a ser enviada.
Marcio> Acho que a dificuldade está em saber usar o módulo IPC::Run. Já fui à
Marcio> página da documentação, mais não entendi muito bem, acho que eu
Marcio> decorrência da minha limitação em Perl.
Isso é consequência de você não estar avaliando a variável $out quando
alimenta a variável $in. Você teria que fazer algo assim:
$in .= "connect(10.1.8.192:23)\n";
$in .= "wait(InputField)\n";
$in .= "String(usertest)\n";
pump $h until $out =~ /\Gvalor esperado/
# etc...
Marcio> Alguém já fez algo parecido? Tem exemplos mais completos que possa me passar?
Marcio> Ou sabe onde eu possa achar um bom material?
Marcio> Ou ao invés de usar esse módulo, tem algo mais simples para essa interação?
O IPC::Run não é o módulo ideal pra fazer esse tipo de coisa. Você vai
se dar melhor com o Expect.
my $exp = Expect->spawn('s3270');
my $cmd1 = "connect(10.1.8.192:23)\n";
$cmd1 .= "wait(InputField)\n";
$cmd1 .= "String(usertest)\n";
$cmd1 .= "wait(InputField)\n";
$cmd1 .= "String(passtest)\n";
$cmd1 .= "Ascii(0,0,24,80)\n";
my $cmd2 = "ENTER\n";
$cmd2 .= "wait(1, Seconds)\n";
$cmd2 .= "wait(Unlock)\n";
$cmd2 .= "wait(InputField)\n";
$cmd2 .= "String(A4L2)\n";
$cmd2 .= "Ascii(0,0,24,80)\n";
$exp->send($cmd1);
$exp->expect(100, [
qr/resposta cmd1: (.+)/ => sub {
my $self = shift;
# $resposta vai ter o que casou com (.+)
my($resposta) = $self->match_list;
# faça algo com $resposta aqui
# enviar segundo comando
$self->send($cmd2);
exp_continue;
},
qr/resposta cmd2: (.+)/ => sub {
my $self = shift;
my($resposta) = $self->match_list;
# etc...
exp_continue;
},
timeout => sub { die 'o sistema parou de responder' }
]);
As subrotinas à direita só são executadas se a expressão à esquerda
casar com saída do s3270, basicamente, é uma máquina de estados. Além
disso, o Expect é desenvolvido levando em consideração que você está
conectado em um terminal, então ele já converte sequências de escape e
coisas do gênero, coisa que o IPC::Run não faz e que pode complicar sua
vida.
Marcio> O cliente usa Mainframe IBM e tem um ERP rodando nele que é acessado
Marcio> em estações Windows com o Extra!. Tem também outra aplicação em Linux,
Marcio> feito em várias linguagens, e essa aplicação precisa trocar alguns
Marcio> dados com o Mainframe. No Windows alguns usuários avançados usam
Marcio> automação OLE para fazer scripts em Excel e ler dados dele,
Marcio> funcionando muito bem.
Marcio> A interface entre os dois aplicativos não existe, assim como o sistema
Marcio> do Mainframe não tem mais manutenção ou qualquer outra forma de
Marcio> acesso, não sendo possível mexer nele e ninguém tem acesso ao OS, só a
Marcio> empresa que faz a manutenção. Assim há um trabalho muito complicado de
Marcio> ficar atualizando informações entre os dois sistemas, e está gerando
Marcio> muitos erros. Está fora de cogitação qualquer ideia que tenha que
Marcio> mexer no Mainframe.
Marcio> A ideia é que o script Perl navegue pelas telas lendo e inserindo
Marcio> dados, assim como os scripts em Excel fazem usando a automação OLE do
Marcio> Extra!.
Que beleza... :)
Marcio> Pelo que entendi esse s3270 é para isso mesmo, o duro é só saber como usar.
Marcio> Em tempo, o que estou fazendo é para facilitar a integração do sistema
Marcio> de telefonia com o CRM.
Olha, na real você só está adiando a dor e o custo de trocar o TN3270
por algo mais manutenível. Isso vai quebrar teu galho agora, mas em
algum momento no futuro, vai aparecer um requisito muito simples mas que
vai ficar caro de implementar por conta da complexidade adicional de
interagir com o sistema dessa forma. Isso sem nem levar em consideração
os bugs que podem existir dentro do s3270 e do Expect, que podem e vão
explodir na hora que você menos esperar e vai ser muito difícil de
consertar. Eu sugiro que você implemente isso como medida provisória e
planeje uma migração definitiva, se puder. Se não puder, meus pêsames,
você está montado numa bomba-relógio sem ponteiros.
--
Eden Cardim
+55 11 9644 8225
Insolide TI Ltda.
http://insoli.de
More information about the SaoPaulo-pm
mailing list