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

Marcio - Google marciorp at gmail.com
Tue Jul 10 10:44:23 PDT 2012


Olá Gabriel,

   Se me enviar vou ficar muito grato. Apesar da minha ser
obrigatoriamente em Linux, acredito que possa aproveitar o
conhecimento e lógica da sua.

   Não sei as regras da lista para envio de arquivos, mais pode enviar
para o meu e-mail marciorp em gmail.com

Abs,

Marcio.



Em 10 de julho de 2012 00:43, Gabriel Vieira
<gabriel.vieira em gmail.com> escreveu:
> 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
> =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


More information about the SaoPaulo-pm mailing list