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

Marcio - Google marciorp at gmail.com
Fri Jul 13 10:36:35 PDT 2012


Em 13 de julho de 2012 09:09, Eden Cardim <edencardim em gmail.com> escreveu:
>>>>>> "Marcio" == Marcio  <- Google <marciorp em gmail.com>> writes:
>
>     Marcio> Olá o código ai, é o mesmo exemplo só que usando o IPC::Run. Por
>     Marcio> desencargo, rodei os dois agora a pouco novamente, e mesma coisa. Com
>     Marcio> o Expect dá erro, e com o IPC:Run não.
>
>     Marcio> #!/usr/bin/perl
>
>     Marcio> my @s3270 = s3270;
>
>     Marcio> use IPC::Run qw( start pump finish timeout );
>     Marcio> $IPCRUNDEBUG=details;
>
>     Marcio> my $h = start \@s3270, \$in, \$out, \$err, timeout( 100 );
>
>     Marcio> $in .= "connect(10.1.8.192:23)\n";
>     Marcio> $in .= "wait(InputField)\n";
>
>     Marcio> finish $h or die "s3270 returned $?";
>
>     Marcio> warn $err if $err;
>     Marcio> print $out;
>
> Não tem como isso estar funcionando porque o start() não faz IO, ele só
> inicia os processos, os comandos que você mandou no $in não vão ser
> todos enviados pro s3270 até você rodar pump().

Mais tá ... :-) ... ai é o começo da história lá nas minhas primeiras
msgs. O IPC::Run só enviava os comandos e me dava o retorno após o
"finish $h ...", o que era um problema, pois após a conexão também era
fechada.
Estou rodando exatamente esse código e tá conectando certinho.

>
>     Marcio> Saída no terminal:
>
>     Marcio> U U U C(10.1.8.192) I 4 43 80 0 0 0x0 0.167
>     Marcio> ok
>     Marcio> U F U C(10.1.8.192) I 4 24 80 15 34 0x0 -
>     Marcio> ok
>
> Como você sabe que essa é a sequência correta? Onde está a resposta ao
> "wait(InputField)"?

As duas primeiras linhas são a resposta do "Connect", e as duas finais
a resposta do "wait".
Essa sequencia quer dizer:
* Primeira linha, referente ao "connect(10.1.8.192:23)\n": U U U
C(10.1.8.192) I 4 43 80 0 0 0x0 0.167
U = Keyboard State, [U]nlocked
U = Screen Formatting, [U]nformatted or in NVT mode
U = Field Protection, [U]nprotected or unformatted
C(10.1.8.192) = Connection State, [C]onnected(host)
I = Emulator Mode, [I] 3270
4 = Model Number, [4] 80 Columns x 43 Rows
43 = Number of Rows
80 = Number of Columns
0 = Cursor Row, the current cursor row (zero-origin).
0 = Cursor Column, the current cursor column (zero-origin).
0x0 = Window ID, the X window identifier for the main x3270 window, in
hexadecimal preceded by 0x. For s3270, ws3270 and c3270, this is zero.
0.167 = Command Execution Time
* Segunda linha, referente ao "connect(10.1.8.192:23)\n": ok = comando
executado com sucesso
* Terceira linha, referente ao "wait(InputField)\n": U F U
C(10.1.8.192) I 4 24 80 15 34 0x0 -
U = Keyboard State, [U]nlocked
F = Screen Formatting, [F]ormatted
U = Field Protection, [U]nprotected or unformatted
C(10.1.8.192) = Connection State, [C]onnected(host)
I = Emulator Mode, [I] 3270
4 = Model Number, [4] 80 Columns x 43 Rows
24 = Number of Rows
80 = Number of Columns
15 = Cursor Row, the current cursor row (zero-origin). [Posição do
campo para digitar o usuário]
34 = Cursor Column, the current cursor column (zero-origin). [Posição
do campo para digitar o usuário]
0x0 = Window ID, the X window identifier for the main x3270 window, in
hexadecimal preceded by 0x. For s3270, ws3270 and c3270, this is zero.
- = Command Execution Time
* Quarta linha, referente ao "wait(InputField)\n": ok = comando
executado com sucesso

>
>     Marcio> Na verdade não sou especialista também, mais ele processa
>     Marcio> cada linha como um comando individual, e no exemplo ai o
>     Marcio> primeiro é para conectar no host.
>
> "Ele" quem?

Ele = s3270

Quando você roda o c3270 (modo interativo) pode passar um parâmetro
que ele cria um log das operações, tipo a sequencia de comando do modo
scripting. E já fiz isso e usei como base para os comandos que envio
para o s3270.

>
>     Marcio> Quando eu rodo ele no modo interativo, onde vou digitando os
>     Marcio> comando, no final de cada linha teclo <ENTER> e ele processa
>     Marcio> o comando.
>
> Não é porque funciona assim no modo interativo que vai necessariamente
> funcionar assim no modo de scripting.

Ai deu um nó. Se eu rodo o s3270 no "prompt" do shell ele abre um
"prompt" para mim digitar os comando, diferente do c3270, e seu eu
digitar esse comandos ("connect, wait, string")  e no final de cada
linha teclar <ENTER>, ele executa as ações certinho.

>
>     Marcio> No script o \n faz a função de teclar o <ENTER> no modo
>     Marcio> interativo.
>
> Não necessariamente, olha isso:
> http://x3270.bgp.nu/s3270-man.html#NVT-ANSI-Mode
>
> Você precisa descobrir se o <ENTER> no modo interativo é realmente
> equivalente ao \n no modo de scripting.
>

Sim, equivale. Tenho 99,99% de certeza pelo seguinte:
1. Tanto no IPC quanto no Expect o s3270 está sendo chamado da mesma
forma, sem nenhum parâmetro, então os "mapas" de caracteres  em uso
devem ser os mesmos;
2. Quando executo o s3270 diretamente no shell e entro com os comando,
no final de cada linha eu teclo <ENTER> e o comando e submetido e
funciona. No arquivo "trace", as linhas são terminadas com \n;
3. No poucos exemplos que vem com s3270 e demais, sempre cada linha de
comando e terminada com o \n; e
4. Estou usando dois comandos nos exemplos, exatamente iguais, porém
um usando o IPC e outro o Expect para interagir com o s3270. Usando o
IPC funciona, usando o Expect aparece e ^M no final da linha de
comando e dá erro no comando, retornado pelo s3270. O erro não é
gerado pelo host, mais sim pelo s3270 que não entende o ^M no final da
linha, e posso afirmar porque rodei o exemplo (perl) com a VPN
desconectada, então não teria com o s3270 ter submetido alguma coisa
para o host, e quando rodei com a VPN conectada, o retorno foi
exatamente o mesmo. Também tentei colocar parametros errados no
comando e executar usando o exemplo do IPC, o retorno é outro
totalmente diferente, e vem do host, ou seja, o s3270 "entendeu" o
comando e mandou ao host, ai o host retornou erro, mais o status de
retorno do s3270 foi "ok", pois o comando estava certo.

>     Marcio> Então, isso que não entendi. Se o retorno não casar com nenhuma
>     Marcio> expressão ele vai cair aqui, mais só depois de ocorrer o timeout, ou
>     Marcio> seja, mesmo que ocorra algum retorno, ele só vai processar depois de
>     Marcio> 100 segundos (ou o que eu definir). É isso? Se for, volta a pergunta,
>     Marcio> tem como colocar uma expressão default que seja processada antes do
>     Marcio> timeout se nenhuma das outras casar?
>
> E como a biblioteca vai saber que nenhuma expressão casou, se ainda não
> passou o timeout? Pode ser que a sequência esperada ainda esteja por vir
> no stream de dados. Então não faz sentido ter uma "expressão default".

Entendi, tem razão.

>
>     Marcio> É que fico até constrangido fazendo perguntas tão banais a
>     Marcio> mestres ... :-) Brinco com microcontroladores (eletrônica)
>     Marcio> por hobby, e a coisa mais difícil e conseguir ajuda de algum
>     Marcio> expert/engenheiro nos fóruns especializados da areá. Os kras
>     Marcio> se consideram superiores, e nunca foram aprendizes e tiveram
>     Marcio> dúvidas.
>
> Se o teu problema fosse banal eu já tinha te mandado um RTFM. :)

O que é RTFM ???? Essa eu não conheço ... :-)

>
>     Marcio> Então, para mim o TN3270 não tem muito mistério ou o que
>     Marcio> mexer, pois quando eu conecto eu já caio em uma tela da
>     Marcio> aplicação e a partir dai é digitar usuário/senha e ir
>     Marcio> selecionando opções no menus e depois digitando e lendo
>     Marcio> dados. Eu não uso comandos e outros recursos. Quando conecto
>     Marcio> pelo s3270 no modo interativo ou mesmo o c3270, eu consigo
>     Marcio> fazer todas as operações necessárias.
>
> Lamento, mas não é tão trivial assim, o mistério é que o que você vê na
> tela do emulador de terminal não é necessariamente o que passou pelo
> stream de dados, senão você não precisaria de um emulador, era só
> conectar direto via telnet. E eu não sei até que ponto o s3270
> não-interativo manipula esses dados pra te entregar. Boa parte desse
> problema é que tem outros fatores em cena e não tenho como diagnosticar
> a resposta vinda do servidor. Pode ser um problema de codificação de
> caracteres (aposto que esse IBM está usando EBCDIC, que é um inferno),
> pode ser um problema de buffering, pode ser algum detalhe na forma como
> o s3270 está sendo invocado, etc. etc.

Sim, está certo sobre ser EBCDIC ... coisas que só a IBM faz pela gente ... :-D

Pois é, ai que está e não consigo entender. Se rodo o s3270 no shell e
vou digitando os comando no prompt dele e teclando <ENTER>, funciona.
Agora se uso o Expect para carregar uma "instancia" dele (s3270) e
enviar os comandos, não funciona.
Nas duas formas estou usando scripting, certo? A diferença é que na
primeira eu estou digitando diretamente no prompt dele e na segunda um
módulo/biblioteca está fazendo isso, mais ele (s3270) não sabe a
diferença, ou estou errado?
Não tenho certeza, mais o problema é esse "misterioso" ^M que ta
aparecendo no final da linha quando envio as "strings" de comando para
o s3270 via Expect.

>
> A forma mais objetiva de resolver isso é saber o que esperar do terminal
> em termos de dados brutos e avaliar as possibilidades quando você não
> obtiver o que espera.

Ao nível de tcp/ip conectar diretamente no host? Assim eu teria que
escrever um s3270 da vida, ou não?

>
>     Marcio>  Outro detalhes é que o exemplo com o IPC::Run funcionou,
>     Marcio> então não pode ser alguns detalhe do Expect?
>
> Não, não funcionou, é que você ainda não tá usando direito. :)

Sim, isso eu imagino ... a questão é, o que estou fazendo de errado
com o Expect?
Conheço o ditado que diz: Computadores não erraram, fazem exatamente o
que os programadores mandam e nada mais!

>
> --
> Eden Cardim
> +55 11 9644 8225

Abs,

Marcio


More information about the SaoPaulo-pm mailing list