No mundo da modernização de sistemas, nem sempre é possível reescrever o código legado. Muitas das maiores instituições financeiras e seguradoras do mundo ainda rodam seus núcleos em mainframes IBM. O desafio surge quando precisamos conectar uma aplicação web moderna ou um script de automação a essas telas verdes antigas.
É aqui que entra o s3270.
O que é o s3270? Link para o cabeçalho
O s3270 é um emulador de terminal scriptável e headless (sem monitor/interface gráfica) para sessões IBM 3270. Ele faz parte da suíte open-source x3270.
Enquanto um emulador tradicional (como o PCOMM ou o próprio x3270) desenha a tela para um humano ler e teclar, o s3270 roda em segundo plano. Ele abre a conexão, mantém o estado da sessão na memória e permite que outros programas “digitem” e “leiam” a tela através de comandos.
Por que ele é essencial?
- RPA (Robotic Process Automation): Permite criar robôs que navegam no mainframe para extrair dados ou cadastrar informações sem intervenção humana.
- Modernização de Interface: Você pode criar uma página Web bonita em React ou Vue.js onde, quando o usuário clica em “Consultar Saldo”, o backend (PHP, Python, Java) aciona o s3270 para buscar esse dado na tela verde e devolvê-lo formatado.
- Testes Automatizados: Equipes de QA utilizam o s3270 para validar se as alterações no COBOL não quebraram o fluxo das telas.
A Arquitetura da Automação
O fluxo de funcionamento geralmente segue esta lógica:
- O Gatilho: Um script (Python, PHP, Shell) inicia o processo
s3270. - O Comando: O script envia comandos de ação (ex:
Connect,String,Enter). - O Feedback: O s3270 processa o comando no host IBM e retorna o output (o texto da tela) para o script.
Exemplos Práticos Link para o cabeçalho
Para interagir com o s3270, a melhor prática não é chamar o executável cru e tentar parsear o texto manualmente, mas sim usar bibliotecas (wrappers) que gerenciam a conexão e o tempo de resposta (timing) do mainframe.
1 - Exemplo em Python
Em Python, a biblioteca mais robusta é a py3270. Ela abstrai a complexidade de gerenciar o processo.
Cenário: Conectar, fazer login e extrair um texto da tela.
Instalação: pip install py3270
from py3270 import Emulator
# Inicializa o emulador (certifique-se que o s3270 está instalado no OS)
em = Emulator(visible=False)
try:
# 1. Conectar ao host
em.connect('mainframe.exemplo.com')
# 2. Esperar a tela carregar (espera o campo 'Userid' aparecer)
# Mainframes são assíncronos, esperar é crucial!
em.wait_for_field()
# 3. Preencher Login
em.send_string('MEU_USUARIO')
em.send_enter()
# Esperar o próximo campo (Password) e preencher
em.wait_for_field()
em.send_string('MINHA_SENHA')
em.send_enter()
# 4. Navegar e Extrair Dados
# Supondo que após o login, queremos ler o saldo na linha 5, coluna 20
em.wait_for_field()
# Lê 15 caracteres a partir da linha 5, coluna 20
saldo = em.string_get(5, 20, 15)
print(f"O saldo extraído do mainframe é: {saldo.strip()}")
# 5. Fazer Logoff (Boa prática)
em.send_string('logoff')
em.send_enter()
except Exception as e:
print(f"Erro na automação: {e}")
finally:
# Fecha o processo s3270
em.terminate()
2 - Exemplo em PHP
No PHP, é comum usar o s3270 para criar APIs que expõem funcionalidades do mainframe. Como não há uma biblioteca padrão tão onipresente quanto a py3270, muitas vezes usamos proc_open para interagir diretamente com o processo ou bibliotecas específicas da comunidade (como gomoob/php3270).
Abaixo, um exemplo usando uma abordagem direta com uma classe wrapper simplificada para ilustração.
Cenário: Rodar um script s3270 pré-definido para buscar um status.
<?php
class MainframeAutomator {
private $host;
public function __construct($host) {
$this->host = $host;
}
public function consultarStatus($usuario) {
// Montamos um script de ações para o s3270
// O s3270 aceita comandos via stdin ou arquivo
$comandos = [
"Connect({$this->host})",
"Wait(Unlock)",
"String($usuario)",
"Enter()",
"Wait(Unlock)",
// O comando Ascii lê a tela inteira para podermos processar
"Ascii()"
];
// Convertemos o array em uma string única
$inputScript = implode("\n", $comandos) . "\nquit\n";
// Executamos o s3270 passando os comandos
// 2>&1 garante que pegamos erros também
// s3270 -model 3278-2 define o tamanho da tela (80x24 padrão)
$process = proc_open('s3270 -model 3278-2', [
0 => ['pipe', 'r'], // stdin (nós escrevemos aqui)
1 => ['pipe', 'w'], // stdout (nós lemos daqui)
2 => ['pipe', 'w'] // stderr
], $pipes);
if (is_resource($process)) {
// Envia os comandos para o s3270
fwrite($pipes[0], $inputScript);
fclose($pipes[0]);
// Lê a resposta (a tela do mainframe)
$output = stream_get_contents($pipes[1]);
fclose($pipes[1]);
proc_close($process);
return $this->parseOutput($output);
}
return false;
}
private function parseOutput($tela) {
// Lógica simples de regex para achar um padrão na tela capturada
// Exemplo: Procurar "STATUS: ATIVO"
if (preg_match('/STATUS:\s+(\w+)/', $tela, $matches)) {
return $matches[1];
}
return "Status não encontrado";
}
}
// Uso
$mf = new MainframeAutomator('mainframe.interno.com');
$resultado = $mf->consultarStatus('USER123');
echo "O status do usuário é: " . $resultado;
?>
Dicas de Ouro para Automação com s3270
- Respeite o “Unlock”: O erro mais comum é o script enviar comandos mais rápido do que o mainframe consegue processar. Sempre use comandos de espera (
Wait(Unlock)ouwait_for_field) antes de enviar a próxima string. - Mapeamento de Tela: Mainframes têm tamanho fixo (normalmente 24 linhas por 80 colunas). Mapear exatamente onde os dados aparecem (coordenadas X, Y) é vital.
- Segurança: Evite hardcode de senhas nos scripts. Use variáveis de ambiente ou cofres de senha para injetar as credenciais no momento da execução.