It must be very easy to write bad documentation – because there is so much around!

There was a chat about the joy of writing technical documentation (and blog posts), one person said they loved doing it, and someone else said it was often looked down as an easy job, for those that cannot code.

I see technical writing is a skill that not every one has. For example it requires empathy – knowing how someone else feels. It is a bit like breathing. Every one can do it. As a singer you need to learn how to breathe to get the music to all the audience.

There are two view of communicating

  • What the audience want’s to hear
  • What I want to tell the audience

I went to a presentation about Greek architecture. Most of the presentation was of pictures of the speaker and his friends sitting in cafes in Greece. In one or two pictures was some architecture. This is an example of “What I want to tell the audience”. The audience wanted to hear about architecture – and having no cafes would have been a bonus.

When you write, you need to consider why people are reading the documentation

  • Is it for a narrative story? “Begin at the beginning, and go on till you come to the end: then stop” said the King of Hearts in Lewis Carroll’s Alice’s Adventures in Wonderland.
  • Is it to find the answer to a question? This might involve searching for text in the document, and the reading will unlikely to be sequential.

You might want to write down a list of questions that you think a reader may have when reading your documentation. You then use these questions as headings. There is a difference between section headings:

  1. Renewing a digital certificate
  2. My certificate has expired. What do I need to do?

The second one is likely to be the question in the reader’s mind, and get a response “Yes – that’s it”.

What knowledge do you expect the reader to have?

If you need to include background information, put it in a section called background. The experienced person can then skip. If you mix background and useful content, then if you speed read the document you might miss the nugget.

People learn in different ways

  • Some people learn best reading
  • Some people learn best by listening
  • Some people learn best by doing

If you can, give examples of instructions the reader can follow themselves.

Some examples of bad documentation

I hired a car. It was a modern hybrid, with a computer screen, and half the normal buttons and controls. The instruction manual for the car was hundreds of small pages long. The first 20 or so pages were about the benefits of a hybrid car. Then followed instructions for fitting a car seat. I could not find the instructions on how to use the handbrake – which was not in the index. I think I eventually found it as “Automatic brake”.

We had great problems parking the car, because it kept complaining “Key not in car” and refusing to lock the doors.

I suggested to the car hire company that they provide one laminated piece of A4 paper with big print with

  • How to adjust the driver’s seat
  • How to adjust the wing mirrors
  • How to start the car
  • How to stop the car and leave it.

Configuring a product

About 40 years ago I had to test installing CICS on VSE.

The instruction were along the lines of

  • define this data set,
  • define that data set,
  • define this VSAM file,
  • define this VTAM APPLID…
  • Now start it up. “It will give a successfully started message”

There were more than 40 things you had to define.

When it failed, as it usually did, you got a message like “££BOPEN failed” and no information about what have failed to open. You had to go through every step and check the definitions.

I worked with the developer and a very good writer and we came up with a script

  1. Define the minimal CICS JCL set every thing possible to no. For example DUMP=NO. There were about 15 lines of JCL.
  2. Start CICS – it it fails check the definitions
  3. Stop CICS
  4. Define the DUMP data sets
  5. Change the option DUMP=NO to DUMP=YES
  6. Start CICS – it it fails check the dump data set definitions
  7. Define something else, change the option, start … stop…

If it failed, then it was obvious what caused the problem. It was the definition you just added.

This was shipped as the install documentation and customers loved it.

A few years later I was involved in the product again, and all of the useful stuff had been stripped out, and the instructions were like the original set of instructions. The tester had his set of “testing JCL” which he ran to make sure it worked.

The tester did not try to type the definitions in with all of the typical user errors. You need to have people with the appropriate level of skill to test the product, and read the documentation. Appropriate might be skilled in the platform – but low knowledge about the product. Having people skilled in the product doing the basics is wrong. We had managers do the install – that was great because they did not understand the technical level.

You need to approach testing and documentation from the user’s perspective – not from your perspective – this is the empathy I mentioned above.

Don’t repeat … point to it, and add value

I was researching how to do something, and there were many articles about how to do it. Some were short, some were long, and they all covered the basics – but not many articles covered the next step after the basics.

It would be better for every one if some of the people had written

  • “This topic is well documented here… so I will not repeat it. Following on from this, the next, more complex thing to do is …”.

There are many articles on how to create a digital certificate on Linux. My follow-on questions include

  • How to I use a second certificate, or how to I use a second certificate authority certificate in the same scenario?
  • If I want to invalidate a certificate – how do I do it?
  • If my certificate expires what do I need to do.

These questions are not usually covered.

Signposting

If the whole content fits on one page, you may not want signposts. If it is a long document (more than a page or two) to need to show the document structure.

You need a table of contents, with links to the text to help people understand the document layout, and where to go. At the top of a blog post may be text like

  • Setting up the Certificate Authority
  • Setting up the certificate
  • …
  • If I want to invalidate a certificate – how do I do it?
  • If my certificate expires what do I need to do?

Give the high level view and then go into more detail

For a complex project start high and work your way into the complexity. For one very complex presentation I started at the high level, then went through it again in more detail, and then a third time in great detail. At each detailed step the audience knew where they were going, because they had already been along the path.

I went to a presentation on an introduction to a certain data protocol. By slide 3 we were looking at all of the fields in the data header. I did not know what the protocol was for… so knowing all the details of fields was wasted on me when I didn’t know what the protocol did.

Someone may not know what you know.

Ensure that you explain terms, or the first time you use a term which may not be generally known; give a link to a definition. Those that know what the term means, will not go to the link. Those that do not know – can go and find out.

I have been working on a presentation about TLS (Transmission Link Security). I got to a point where I had to describe the different sorts of hashing available. I realised I needed a page explaining what Hashing data entails before describing TLS.

Before describing the very complex description of the TLS hand shake. I described how a conversation between someone and the Milk Management team in the EU might work.

  • You: (phoning Brussels) Hello I speak English and French, I would like to talk to someone in the Milk department
  • Them: Hello – we will speak English, my name is… Who are you…

Because the concepts were similar, explaining the TLS handshake was much easier.

Keep it simple

Explain what is needed and do not include information which may only confuse, or may never be used.

Someone explained a protocol to me it went along the lines of

  • At offset 0 is an eye catcher ABCD
  • At offset 4 is the length of the control block
  • At offset 8 is the function 0 = start, 2 = query, 3 = terminate
  • At offset 12 is the date…

The reply has

  • At offset 0 is the eyecatcher
  • ..
  • At offset 8 is the return code – 0 means it worked successfully

At the introduction level I do not need to know the offsets or the values. Several values are not of interest until I start trying to program the protocol,

My description of the protocol was like

There are several fields sent to start the session. The important one is

  • …
  • function. This has the value start, query or terminate
  • …

The response has several fields. The important one is

  • …
  • return code – 0 if it worked else a code you can look up HERE to see why it failed.

Afterthoughts

  • I saw this article as a sequential read through – perhaps as a basis for a talk at a conference next year?
  • It is a long article. I should have used sign posts, or section headers at the top.

Is it my new glasses, or have my x3270 sessions gone out of focus?

I’m running on Ubuntu Resolute Racoon, and after a recent update, my x3270 sessions connecting to z/OS all look out of focus, or like my glasses are dirty.

I think that something has changed in the fonts that are used, or my screen sizes, so when data is displayed it is having to fake the font.

I define a 3270 using a command like

x3270 -model 5 -title mstcon mstcon@localhost:3270  &

where mstcon is the short name.

I needed to be able to change the size of the 3270 screen, so the fonts were clear.

The root problem was the laptop’s screen was defined as scale 125%.  Changing this to 100% and restart the 3270 sessions fixed it.

Third attempt at fixing it.

The easiest way of fixing the problem was to use

export DPI=240
x3270a -model 5 -title mstcon mstcon@localhost:3270 &

This may all be connected with X11 being removed from Ubuntu 26.04, and Ubuntu using Wayland instead. The XWayland code making the system look like X11 may have a couple of hickups.

The information below is from my journey to getting a readable screen.

What is the size of my screen?

You can use the wmctrl command to display information about the screen. wmctrl interacts with the X11 window manager.

wmctrl -l -G

This lists the geometry of all the screens

0x00600169 -1 396  478  2496 1520 ColinNew mstcon
0x00c00169 -1 794 702 2496 1582 ColinNew colin
0x00e00169 -1 794 764 2496 1520 ColinNew tso

Where

  • ColinNew is the name of my userid
  • mstcon is the name of my x3270 window
  • 396 478 is the position of the top left corner of the window,
  • 2496 1520 is the width and height of the window

You can change the configuration using

 wmctrl -r  colin  -e  1,744,618,2496,1582 

You can grab the edges of the x3270 window, and make adjust the size till it looks right, then use the wmctrl -l -G to capture the geometry – and update your wmctrl … -e command.

Or you can do it with X3270

x3270 ... -geom 2496x1582+711+618 ...

Where -geom is -geometry widthxheight+x+y .

The font size jumps!

There are a set of fonts, as you change the size of the screen, for example make it half an inch narrower, at some point it may reconfigure, and suddenly use a smaller font (with lots of space around the content). You should size the window so it is wide enough and high enough for the font size, without wasting space around the content.

My glasses?

I also had a new pair of glasses, and have to position my head to be able to get the windows in focus. Because I keep my 3270 sessions at the top of my screens, I have to tilt my head back slightly!

Update

I did the following commands


sudo apt install fonts-3270
sudo apt install xfonts-x3270-misc
sudo sudo fc-cache -f -v

And x3270 suddenly got better with readable fonts etc..

Resetting the IBMUSER password on the ZD&T z/OS 3.2 stock image

I was sent this useful document from Dan Kalmar.

The IBM documentation on the initial logon to the ZD&T image in the “standard stock image” may not always work. The information below gives an alternative way of getting in.

Environment

  • Emulator ZD&T Personal Edition 14.2.8 (z1091 1.12.59.17), Ubuntu host
  • Image IBM z/OS 3.2 Dev & Test Stock Image for ZD&T PE 14.2.20 (built 2026-09-08)
  • IPL ipl DE27 parm DE28A0M (SYSRES Z32VS1 at DE27, IODF/LOAD on OPEVS1 at DE28)

The problem

The stock image ships with a randomized IBMUSER password. IBM’s documented procedure for Personal sEdition is to edit the password-injection file on the ZDTDPY volume, include ZDTDPY in the device map and IPL with load parm NV:

pdsUtil ZDTDPY ZDT.PASSFILE/PASS0 --extract (edit line 1 of PASS0.txt, 8 chars)
pdsUtil ZDTDPY ZDT.PASSFILE/PASS0 --overlay
ipl DE27 parm DE28NV

On this system that did not work. ZDTDPY was online with the edited PASS0, the IPL used DE28NV, yet TSO IBMUSER still failed with:

IKJ56474I USERID OR PASSWORD IS INCORRECT OR NOT AUTHORIZED

No console message referred to ZDTDPY, so the injection step did not appear to run. RACF commands from the console are refused as well:

IRRV003I (<) YOU ARE NOT ALLOWED TO ISSUE THE LISTUSER COMMAND
AS AN OPERATOR COMMAND

so the password cannot be reset from the console, and the usual ADCD defaults (IBMUSER / ADCDMST) are rejected too. (Whether the 14.2.20 image needs the matching 14.2.20 emulator for the injection to run is an open question with IBM support.)

Caution: do not keep retrying logons — RACF will revoke the userid after a few failures.

The way in

The image ships two pieces that together allow a job to run with authority, without anyone logging on:

  • SYS1.PROCLIB(SUBMIT) on OPEVS1 — a started task that copies a member to the internal reader. It is
    started with S SUBMIT,DS=dsname,M=member.
  • IBMUSER.JCL(SSHKYCP) on STGVS1 — a sample job (shipped to install an SSH key for IBMUSER). Its JOB card has no USER=, so the submitted job runs under the SUBMIT started-task user, which has enough authority to update IBMUSER.

The members can be read and rewritten from Linux with pdsUtil, the same way PASS0 is. So we replace the SSHKYCP member with a job that issues an ALTUSER, then let the shipped SUBMIT task run it at IPL time.


Key constraint: pdsUtil –overlay is an update-in-place — the replacement file must have exactly the same number of records as the original member. SSHKYCP is 26 records, so the replacement job is padded with comment lines to 26.

Procedure

All Linux commands run as the ZD&T user (ibmsys1). The volumes directory below is this system’s (/media/mybook6/z32/volumes) — substitute your own.

Step 1. Shut down z/OS and stop the emulator

awsstop

Step 2. Back up the volume that holds IBMUSER.JCL (STGVS1 here)

cd /media/mybook6/z32/volumes
cp STGVS1 ../STGVS1.bak

Step 3. Extract the SSHKYCP member and keep an untouched copy

mkdir -p ~/z32check && cd ~/z32check
pdsUtil /media/mybook6/z32/volumes/STGVS1 IBMUSER.JCL/SSHKYCP --extract
cp SSHKYCP.txt SSHKYCP.orig.txt

–extract writes SSHKYCP.txt (ASCII) into the current directory. Note the record count reported (26).

Step 4. Replace SSHKYCP.txt with the reset job, padded to 26 records

The job below runs ALTUSER under TMP/E (IKJEFT01). Keep it at exactly 26 lines. Put your own 8-character password (uppercase + digits) in place of NEWPASS1 on the ALTUSER line:


//PWRESET JOB CLASS=A,MSGCLASS=X
//* Reset IBMUSER password. Runs under the SUBMIT STC user (no USER=).
//* Start with: S SUBMIT,DS=IBMUSER.JCL,M=SSHKYCP
//*
//* --- padding so the member stays 26 records (pdsUtil --overlay rule) ---
//*
//*
//*
//*
//*
//*
//*
//*
//*
//*
//*
//*
//*
//*
//S1 EXEC PGM=IKJEFT01
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *
ALTUSER IBMUSER PASSWORD(NEWPASS1) NOEXPIRED RESUME
LISTUSER IBMUSER
/*

Confirm the count before writing it back:

wc -l ~/z32check/SSHKYCP.txt # must print 26

Step 5. Write the member back to the volume

cd ~/z32check
pdsUtil /media/mybook6/z32/volumes/STGVS1 IBMUSER.JCL/SSHKYCP --overlay


Success looks like: AWSPDS055I 26 records overlayed PDS member ‘SSHKYCP’. A record-count mismatch instead gives AWSPDS054E … RC=-10 — re-check the line count.


Step 6. IPL and run the job from the master console

cd /media/mybook6/z32 && sh runzpdt_z32


Once BASE Z/OS SUBSYSTEMS HAVE BEEN STARTED appears, on the master console:

S SUBMIT,DS=IBMUSER.JCL,M=SSHKYCP


Watch for $HASP395 PWRESET ENDED (and IEF404I PWRESET – ENDED). If no ICH/IRR error appears, the ALTUSER was accepted.


Step 7. Log on and verify

Dial a TSO terminal (the stock image uses devices 0062–0065 for VTAM; 0060/0061 are MCS consoles) and log on:

TSO IBMUSER (then the new password at IKJ56476I ENTER PASSWORD)

The PWRESET job output is held in class X — its LISTUSER confirms IBMUSER’s status.

Step 8. Restore the original member

Once in TSO, put the shipped SSHKYCP back so the image matches IBM’s.

Edit IBMUSER.JCL(SSHKYCP) in ISPF and paste the original contents (SSHKYCP.orig.txt), or re-run –overlay with the saved original while z/OS is down. Then change the password the normal way and delete the volume backup.

Why this works


The submitted job inherits the SUBMIT started task’s RACF identity (no USER= on the JOB card), and on this image that identity has enough authority to issue ALTUSER against IBMUSER. Nothing bypasses RACF: the job runs as an already-authorized started-task user, which is why it can set a password that console RACF commands are blocked from setting. Everything up to Step 6 is done offline with pdsUtil, the same utility IBM’s own PASS0 procedure uses.

Level independence and suspected root cause

This workaround is independent of the emulator and z/OS release. pdsUtil, SYS1.PROCLIB(SUBMIT), a no-USER= job inheriting the started task’s RACF identity, and ALTUSER are all stable across ZD&T and z/OS levels, so the method works whether or not the PASS0 injection mechanism is present on the image.


The likely reason IBM’s documented PASS0 procedure produced nothing here: the code that reads ZDT.PASSFILE(PASS0) at IPL may require a later emulator than 14.2.8. The image is built for ZD&T 14.2.20; this host runs the 14.2.8 emulator. That would explain why ZDTDPY was online with the edited PASS0 and the IPL used DE28NV as documented, yet no console message referred to the injection and the password was unchanged. This is a hypothesis, not confirmed by IBM — the open question is whether the 14.2.20 stock image requires the matching 14.2.20 emulator for PASS0 injection (and for other functions). If so, applying the 14.2.20 fix pack is the proper fix, and the procedure above is the bridge until then.

Note

This is shared as a working note — verify each step against your own entitlement and IBM documentation. Device numbers, volume serials and paths are specific to this ZD&T system.


How to export and import a Grafana dashboard

Like many things, it is easy once you know how. The instructions on the internet usually missed one tiny critical piece of information. |←

Export a dashboard

In Grafana, select a dashboard. At the bottom of the display select |← (circled in the image). (This was the missing bit of information.)

  • This gives you icons
    • Download
    • Content outline
    • ->|
  • Select Download. This gives

You can either Download the file, or copy to the clip board. Because Grafana is running in a browser, the downloaded file is in your normal Downloads directory. One download had a name dashboard-1791876486315.json

Importing a dashboard

In Grafana, select Dashboards

Select the +^ on the top line, and select import dashboard.

You can drag and drop a file to the area, or select from a file list.