Running z/OS REXX from Persistent TSO Address Space w/Zowe CLI

Dan Kelosky
3 min readOct 11, 2023

Previously we shared how to run z/OS REXX faster with Zowe CLI. One technique described there involved using a persistent (longer running) TSO address space. However, specific details on how to do this were skipped.

Below we’ll look at the steps used to keep a persistent TSO address space to quickly run REXX via something like Zowe Explorer:

Overview

We’ll rely on a script, keep-tso.mjs, (source below) which does three primary things:

  1. runs azowe tso start address-space command
  2. executes any TSO environment initialization commands (e.g. dynamic allocation)
  3. periodically pings the TSO address space to keep it alive

keep-tso.mjs

You can copy this script in a project and keep it in source control:

import { execSync } from 'child_process';
import { writeFileSync } from 'fs';
import { readFileSync } from 'fs';

const KEY_FILE = 'key.txt';
const CMD_FILE = 'cmds.txt';
const MAX_FAIL = 5;
const WAIT_TIME = 1000 * 60 * 5; // 5 minutes (in milliseconds) - milliseconds * seconds * minutes

function start() {
console.log(`Starting TSO...`);
const key = execSync(`zowe tso start as --sko`).toString().trim();
writeFileSync(KEY_FILE, key);

commands().forEach(cmd => {
console.log(`running '${cmd}'`)
send(key, cmd);
});

console.log(`... key was ${key}`);
return key;
}

function ping(key) {
try {
console.log(execSync(`zowe tso ping as ${key}`).toString().trim());
return true;
} catch (e) {
return false;
}
}

function stop(key) {
try {
console.log(execSync(`zowe tso stop as ${key}`).toString().trim());
return true;
} catch (e) {
return false;
}
}

function read() {
try {
return readFileSync(KEY_FILE).toString().trim();
} catch (e) {
}
return `fakekey`;
}

function commands() {
try {
return readFileSync(CMD_FILE).toString().trim().split(/\r?\n/g);
} catch (e) {
}
return [];
}

function send(key, cmd) {
try {
console.log(execSync(`zowe tso send as ${key} --data "${cmd}"`).toString().trim());
} catch (e) {
// do nothing
}
}

function keep() {

let failed = 0;
let key = read();
if (!ping(key)) {
failed++;
if (failed > MAX_FAIL) {
console.log(`failed too many times`);
process.exit(1);
}
key = start();
}
}

// stop(read()); // debug
keep();
setInterval(() => {
keep();
}, WAIT_TIME);

cmds.txt

If you need any one-time initialization commands to run at TSO address space start time, you can create an adjacent file, cmds.txt, and if found, keep-tso.mjs runs the TSO commands found there (to do things like dynamic allocation).

For example:

allocate file(ops$opsy) dummy
allocate file(myexec) dsn('opsmvs.kelda16.ops.dev.rexx') shr
concat file(sysexec myexec)
allocate file(isplog) dummy

In this case, a data set, OPSMVS.KELDA16.OPS.DEV.REXX, is allocated to a SYSEXEC DD.

Running the Script

Ideally, you’ll run the script in a dedicated terminal window (instead of something like the VS Code terminal which tends to crash more often than not):

keep-tso.mjs startup with intential first error

Note that when the script runs, if firsts attempts to ping a previous TSO address space. If the ping fails, it starts a new instance (which is why there is an error message issued in this gif).

When the script runs, it also writes a file, key.txt. This file should be in your .gitignore.

oi.bat

Lastly, you can use Windows batch files (as an example) to recreate a mainframe experience. Here we use a file oi.bat with these contents:

@echo off
set /P TSO_KEY=<key.txt
zowe tso send as %TSO_KEY% --data "oi %1"

This allows you to run oi from your workstation terminal, similar to how you might run oi from a TSO interface:

Running REXX from green screen (left) and workstation terminal (right)

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Dan Kelosky
Dan Kelosky

Written by Dan Kelosky

Likes programming/automation in mainframe (assembler, C/C++), distributed (Node.js), and web development (Firebase, Angular).

No responses yet

Write a response