[SP-pm] Perl para automação em acesso a x3270 IBM

Gabriel Vieira gabriel.vieira at gmail.com
Mon Jul 9 21:43:10 PDT 2012


Olá,

tenho experiência mas via OLE no Windows.. se tiver interesse te envio
a aplicação... (lembro que havia um problema de delay... o terminal
era bem lento pro script e eu não conseguia identificar como
solucionar).. era pra se conectar so SisBB do Banco do Brasil.

Abraços,

2012/7/9 Marcio - Google <marciorp em gmail.com>:
> Olá Eden, obrigado!
>
> Sim, eu vi as páginas e foi nelas que aprendi os comandos de script
> desse apl. A minha dificuldade está com Perl mesmo.
>
> Pois é, como respondi ao Nelson, não consegui usar o pump (pump $h
> until $out =~ /\Gvalor esperado/) porque não sei o que esperar de
> retorno, pode ser qualquer coisa. Tenho que pegar tudo que voltou e
> analisar. Ai acho que entra as expressões regulares.
>
> Quanto ao Expect, desculpa, mais como disse meu conhecimento de Perl é
> bastante limitado, então qual a diferença do IPC::Run e do Expect e
> porque esse é melhor?
>
> Sobre o código com o Expect, não entendi bem.
> $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' }
> ]);
>
>
> Se eu tiver 50 comandos vou ter que "encadear" 50 subs?
> O outro detalhe é que não sei o que esperar de volta, não tem como
> saber, tenho que pegar tudo que voltar. A única coisa que sei é que o
> tamanho do retorno é de no mínimo 1920 caracteres (espaços, números e
> letras).
>
> Imaginei algo assim:
>
> 1. Conecta
> 2. Verifica o retorno para saber se conectou e como
> 3. Envia o primeiro comando
> 4. Lê o retorno
> 5. Chama a função que trata retorno passando como parâmetro o conteúdo
> do retorno
> 6. Envia o segundo comando
> 7. Lê o retorno
> 8. Chama a mesma função que trata retorno passando como parâmetro o
> conteúdo do retorno
> ...
> 100. Desconecta e encerra.
>
> A função que trata o retorno irá varrer a string a procura de
> informações e erros, e dependendo disso, executar outros comandos,
> gravar informações no banco de dados e etc.
>
> Sei que isso é uma gambiarra pronta para explodir, mais o cliente não
> vai trocar o sistema legado que roda a 30 anos sem uma única parada. E
> a minha é a menor de todas, você precisa ver o que o povo faz com
> Excel e VBScript usando automação.
> Alguns módulos já foram para SAP, mais o grosso está no Mainframe, que
> pelo que ouvi falar deve ficar no ar por pelo menos mais 10 anos.
> Eu sou só um grãozinho de areia na TI deles, mexo só com a parte de
> telefonia computadorizada. A TI deles tem mais de 250 pessoas, e eu
> não tenho poder nem de sugestão em relação a sistemas, só mexo com a
> minha área e sou terceirizado ... mais ou menos assim: manda quem
> pode, obedece quem tem juízo ... :-)
>
> Agradeço toda ajuda.
>
> Abs,
>
> Marcio.
>
>
> Em 9 de julho de 2012 16:59, Eden Cardim <edencardim em gmail.com> escreveu:
>>>>>>> "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
>> =begin disclaimer
>>    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>>  SaoPaulo-pm mailing list: SaoPaulo-pm em pm.org
>>  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
>> =end disclaimer
>
>
>
> --
>
> [...]'s
>
> Marcio
> =begin disclaimer
>    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>  SaoPaulo-pm mailing list: SaoPaulo-pm em pm.org
>  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
> =end disclaimer



-- 
Gabriel Vieira


More information about the SaoPaulo-pm mailing list