[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