MQGem Products: Minor Updates

MQGem products licences are time based, allowing you to use the latest version of the product without needing to buy a new licence. One of the advantages of this is described as follows in the manual:-

Features are available sooner
Using this model it is not necessary for us to collect a large group of features together to ‘justify’ a new release of the product. Instead a new release can be made available whenever a new feature is added which is regarded as sufficiently useful since all current users will be able to migrate to the new version at no cost to themselves.

This allows us to do even very small minor updates to the products from time to time. These minor updates are notified to you in a couple of ways. At the end of each month, any minor updates will be included in the News section of our MQGem Monthly newsletter.

In addition to this, minor updates will be tweeted using each product’s hashtag on the day of the upload.

You can see all the minor updates so far using each of the following links. Even if you’re not a twitter user, these posts are all public for you to view. Below each link is an example tweet. Whenever possible, these tweets will include a screenshot to demonstrate the new update.

MO71 Minor Updates

MQSCX Minor Updates

MQEdit Minor Updates

Remember, if you have a minor change you’d like to see to one of our products, please tell us about it. Small updates don’t have to wait for a whole new version!


If you don’t have a licence and would like to try out any of our products then send an email to support@mqgem.com stating which product you’d like to try and a 1-month trial licence will be sent to you.

What’s in Command Levels 90x

MQ90x StairsIBM MQ released Long Term Support release V9.0.0 back in June 2016 which had a Command Level of 900. The subsequent Continuous Delivery releases, V9.0.1 and V9.0.2 have each introduced their own Command Levels, 901 and 902 respectively.

This post captures the changes that are available in each of those Command Levels.

Release Command Level Features protected by Command Level – details below
V9.0.0.0 900 AMS Protection Policy enhancement – Confidentiality Policy
LDAP Authorization on Windows
V9.0.1 901 No changes protected by Command Level
V9.0.2 902 Log management features

AMS Protection Policy enhancement – Confidentiality Policy

With the introduction of Confidentiality Policies in Command Level 900, there is a new attribute on the Set Policy command. A confidentiality policy has no signature algorithm, but does have a encryption algorithm. The Key Reuse feature is applicable to this type of policy. Jon Rumsey has a great write-up of this IBM MQ V9 feature on the MQDev blog, MQ V9 Fast encrypted messages with MQ – Introducing AMS Confidentiality Policies.

AMS Policy

New Attribute MQSC name
See SET POLICY
Look for KC 9000 indicator
PCF constant and values
See Set Policy
Look for KC 9000 indicator
Key Reuse

KEYREUSE

  • DISABLED
  • UNLIMITED
  • 1 – 9999999

MQIA_KEY_REUSE_COUNT (267)

  • MQKEY_REUSE_DISABLED (0)
  • MQKEY_REUSE_UNLIMITED (-1)
  • 1 – 9999999

LDAP Authorization on Windows

Introduced in Command Level 801 on Unix, this feature extended the V8.0.0 Connection Authentication feature which checked your user ID and password, to allow LDAP authorization as well. The fields now available on Windows are the same as those noted in the earlier post for Command Level 801, and are not repeated here.

Log management

With the introduction of Automatic management of linear log extents, and Automatic writing of media images, in Command Level 902, there are new attributes on the queue manager object, queue manager status, and one on queue objects. Mark Whitlock has written about this in an MQDev Blog Post: Logger enhancements for MQ v9.0.2.

Queue Manager Object

New Attribute MQSC name
See ALTER QMGR
Look for KC 902 indicator
PCF constant and values
See Change Queue Manager
Look for KC 902 indicator
Image Schedule

IMGSCHED

  • AUTO
  • MANUAL

MQIA_MEDIA_IMAGE_SCHEDULING (268)

  • MQMEDIMGSCHED_AUTO (1)
  • MQMEDIMGSCHED_MANUAL (0)
Image Interval

IMGINTVL

  • 1 – 999 999 999
  • OFF

MQIA_MEDIA_IMAGE_INTERVAL (269)

  • 1 – 999 999 999
  • MQMEDIMGINTVL_OFF (0)
Image Log Length

IMGLOGLN

  • 1 – 999 999 999
  • OFF

MQIA_MEDIA_IMAGE_LOG_LENGTH (270)

  • 1 – 999 999 999
  • MQMEDIMGLOGLN_OFF (0)
Image Recover Object

IMGRCOVO

  • NO
  • YES

MQIA_MEDIA_IMAGE_RECOVER_OBJ (271)

  • MQIMGRCOV_NO (0)
  • MQIMGRCOV_YES (1)
Image Recover Queue

IMGRCOVQ

  • NO
  • YES

MQIA_MEDIA_IMAGE_RECOVER_Q (272)

  • MQIMGRCOV_NO (0)
  • MQIMGRCOV_YES (1)

Queue Manager Status

New Attribute MQSC name
See DISPLAY QMSTATUS
Look for KC 902 indicator
PCF constant and values
See Inquire Queue Manager Status
Look for KC 902 indicator
Archive Log Extent Name

ARCHLOG

MQCACF_ARCHIVE_LOG_EXTENT_NAME (3208)

  • String of length MQ_LOG_EXTENT_NAME_LENGTH (24)
Archive Log Size

ARCHSZ

MQIACF_ARCHIVE_LOG_SIZE (1416)

Media Log Size

MEDIASZ

MQIACF_MEDIA_LOG_SIZE (1417)

Restart Log Size

RECSZ

MQIACF_RESTART_LOG_SIZE (1418)

Reusable Log Size

REUSESZ

MQIACF_REUSABLE_LOG_SIZE (1419)

Archive Log In Use

LOGINUSE

MQIACF_LOG_IN_USE (1420)

Archive Log Utilization

LOGUTIL

MQIACF_LOG_UTILIZATION (1421)

Reset QMgr command

Updated attribute MQSC name
See RESET QMGR
Look for KC 902 indicator
PCF constant and values
See Reset Queue Manager
Look for KC 902 indicator
Action

TYPE

  • REDUCELOG
  • ARCHLOG

MQIACF_ACTION (1086)

  • MQACT_REDUCE_LOG (10)
  • MQACT_ARCHIVE_LOG (11)
Archived Log

ARCHIVED

MQCACF_ARCHIVE_LOG_EXTENT_NAME (3208)

  • String of length MQ_LOG_EXTENT_NAME_LENGTH (24)
Log Reduction

REDUCE

  • AUTO
  • ONE
  • MAX

MQIACF_LOG_REDUCTION (1422)

  • MQLR_AUTO (-1)
  • MQLR_ONE (1)
  • MQLR_MAX (-2)

Queue Local and Queue Model

New Attribute MQSC name
See DEFINE queues
Look for KC 902 indicator
PCF constant and values
See Change, Copy, and Create Queue
Look for KC 902 indicator
Image Recover Queue

IMGRCOVQ

  • NO
  • YES
  • QMGR

MQIA_MEDIA_IMAGE_RECOVER_Q (272)

  • MQIMGRCOV_NO (0)
  • MQIMGRCOV_YES (1)
  • MQIMGRCOV_AS_Q_MGR (2)

You can get the equivalent information for earlier Command Levels from these posts.

Running User Commands in MO71

MO71 User Commands

The User Commands menu on a queue manager in MO71

Do you have a number of commands, or scripts, or batch jobs that you regularly use against your queue managers? How would like to be able to invoke them from the queue manager menu in MO71? In the latest version of MO71 just released, you can do just that. This might be useful when setting up MO71 for your operations team to use (see Delivering an MO71 Bundle to your MQ team) to pre-configure MO71 with the various scripts they should be using for tasks outside MO71.

MO71 User Command strmqm

A User Command that will invoke strmqm for the queue manager

Of course, not all user commands you might want to run would apply to all queue managers in your MO71 configuration, so when setting up User Commands in MO71 you can say which queue managers they apply to. For example, if your queue manager is local to MO71 you can use commands such as strmqm, but for remote queue manager’s you’ll need some sort of remote script to achieve the same. The easiest way to categorize your queue managers is to put them into various “networks” (MO71’s way of categorizing them – see Can you see your QMgr for the trees?). You could imagine a network called “Local” and another called “Remote” which you can then use to determine whether the User Command that runs strmqm can be used. You can make one User command definition which applies to all queue managers in the “Local” network and use the %q substitution character to pass the queue manager name through to the command.

Here you’ve seen an example of a substitution character allowing you to pull information from the location to build up the command. Other substitutions that pull information from the location details are as follows. If there are other things that might be useful to use from the location details as substitutions in User Commands, let us know.

Insert Meaning
%c Location CLNTCONN connection name
%g Location Group Name
%l Location Name
%q Queue Manager Name

If you need to use any environment variables, for example MQ_DATA_PATH or MQ_INSTALLATION_PATH, these can also be used in substitutions in your User Commands with the following syntax:-

%[MQ_DATA_PATH]
MO71 User Command SSH

A User Command to launch an SSH session to the machine the queue manager is on

For “Remote” queue managers you might want to have quick access to a telnet/putty/ssh session to the machine the queue manager is running on. The session you use might vary based on the platform of the machine. For example, for your z/OS queue managers you might want to start a 3270 session. So there’s another possible network, you could also categorize your queue managers by platform. You can use the %c substitution character to pass the connection name (without port number) through to the command.

These User Commands can run anything you can imagine doing in a script. These might be quite simple wrapper scripts or quite complex scripts. You could use it to run an MQSCX script that generates a report with a known file name, and then open the script with something like notepad to view the results.

mqscx -x -f -C "=import file(C:\MQGem\MQReport.mqx) parms(%1)"
notepad C:\MQGem\Output\MQReport_%1_%2_%3_%4.txt

The User Command would then run the command file:

C:\MQGem\runReport.cmd %q %y %m %d

When generating files, it is common to use dates and times in the file names. The other inserts available as substitutions in User Commands are those you can use to generate dates and time, as follows.

Insert Meaning
%d Day of the month e.g. 16
%D Day of the month e.g. Mon, Tue, Wed
%H Current time hours
%m Current Month e.g. Jan, Feb, Mar
%M Current time minutes
%S Current time seconds
%t Current time in HH.MM.SS format
%y Four digit year

You can also start other programs directly from MO71, and pass in the queue manager name as a parameter where required. For GUI applications make sure the User Command is defined with Hidden set to No or the GUI won’t be visible. If you are an MQSCX user as well as an MO71 user, you may prefer to use MQSCX rather than the MQSC window in MO71 for command line operations. You can create a user command to start an MQSCX session up for the queue manager through a User Command.

The flexibility of running any command scripts means you can do a lot with this, but if you think of other inserts or requirements on this feature, please drop us a line, or leave a comment below to let us know.


The new version can be downloaded from the MO71 Download Page. Any current licensed users of MO71 can run the new version on their existing licence. If you don’t have a licence and would like to try out MO71 then send an email to support@mqgem.com and a 1-month trial licence will be sent to you.

Scripts using foreach on the CCDT

foreachThere are different types of users who use MQSCX. Some like the interactive experience, with tab auto-complete of commands, keywords and objects names. Others like the ability to create and edit CCDT files suitable for any required version of IBM MQ. Others again like the powerful control language which makes writing scripts to interrogate your queue manager a breeze.

Freaking awesome, Paul! I wrote several reporting scripts for a customer a couple of months back. They declined to purchase MQSCX so I was forced to do much of the logic in the script, giving me I have a good basis for comparison of both approaches. The differential in lines of code, complexity and amount of additional billable time I spent would have paid for a site license for several years. The ROI is now more than doubled, possibly even 5x what it was.

User comment on MQSCX – see more at What our customers say

Sometimes those different use cases come together. The control language has a for loop concept where you can easily iterate over all the queue manager objects that are returned by the command server as the answer to an MQSC command, with a script something like this:-

@total = 0
foreach(DISPLAY QLOCAL(*) WHERE(CURDEPTH GT 0))
  @total = @total + CURDEPTH
endfor
print 'Total CURDEPTH =',@total

You can also write scripts that operate, not on queue manager objects, but on the contents of a CCDT file.

With the latest version of MQSCX, you can use the foreach construct on the items in your CCDT file in just same way as above. Here’s a small example:-

@ssl = 0;
foreach(DISPLAY CHANNEL(*) SSLCIPH)
  if (SSLCIPH)
    @ssl = @ssl + 1
  endif
endfor
print 'Found',@ssl,'SSL Channels out of',_numEach

Now with MQSCX V9.0.0 you can use the powerful control language to analyse and manipulate your CCDT files. Another example of using the foreach construct on a CCDT file can be see in Be sure of your CCDT Version


If you are a current MQSCX licence holder, you can simply download the new version of MQSCX and start using it. If you’re not a current licence holder, and you’d like to try out MQSCX, please email support@mqgem.com to request a trial licence.

Only run MQSC script on intended Queue Manager

Correct QMgr?IBM MQ is a robust product and queue managers can run without problems for months, or even years at a time. In fact, often when problems do occur they are the result of human error, and one example of such as error can be running an MQSC script against an unintended queue manager.

I think we have all pushed an MQSC file into the wrong queue manager. 😦

So, the question was asked, how can I ensure that I only run my MQSC script against the queue manager it was intended for?

This is something that MQSCX can help you with. There are a few ways you can do this.

Check that you are connected to the correct queue manager

One way to protect against running an MQSC script against the wrong queue manager is to start the script with a quick test to see which queue manager it is currently connected to and to exit the script immediately if it is found to be administering the wrong one.

if ( _qmgr != "QM1" )
  print "Wrong queue manager! Script expects to be used on QM1"
  leave
endif

_qmgr is an MQSCX system variable that tells you which queue manager you are administering. There are also some others that might be helpful when coding up checks at the start of a script, _connqmgr tells you which queue manager you are connected to, and will be different from _qmgr if you are using a via connection. _client tells you if you are connected as a client. You can see these in action in the DISPLAY DQM for Distributed blog post.

You could also make the check broader and have it query some attribute of the queue manager to determine if it was an appropriate queue manager to run the script against. For example, looking for the word “(Test)” in the queue manager description. This means a script couldn’t accidentally be run against one of your production queue managers. Using this simple technique, each script can be limited to a class of queue managers; Production, Test, Devt and so on.

DISPLAY QMGR DESCR
if (!findstr("(Test)",DESCR))
  print "Queue Manager",_qmgr,"does not appear to be a test QMgr"
  print "Queue Manager",_qmgr,"DESCR(",:n:DESCR,:n:")"
  leave
endif

Have the script connect to the appropriate queue manager

As an alternative, rather than having the script check that the human running it has used the correct queue manager, the script could make the connection itself.

=conn qm(QM1)
if (_lastrc)
  leave
endif
ALTER QMGR ...
DEFINE CHANNEL ...

A script with commands for different queue managers

Having made a script that connects to the correct queue manager before running the commands against it, it is not difficult to make the next step where you can have a script that issues commands on multiple queue managers – has a section for each queue manager prefixed by an =conn command.

=conn qm(QM1)
ALTER QMGR ...
ALTER CHANNEL ...
 
=conn qm(QM2)
ALTER QMGR ...
ALTER QLOCAL ...
 
=conn qm(Q3)
ALTER QLOCAL ...

This is only scratching the surface of what MQSCX can do, but it can certainly make administration of your IBM MQ queue managers less error prone.


If you’re not a current MQSCX licence holder, and you’d like to try out MQSCX, please email support@mqgem.com to request a trial licence.


I was prompted to write this post as a result of this list-server question.

Adding up

When answering this question I offered a suggestion that you could total the number of connections coming over a set of SVRCONN channels by using the following single line in MQSCX.

@total=0;foreach(DISPLAY CHSTATUS(*) CURSHCNV);@total=@total+CURSHCNV;endfor;print @total

This totaled all the CURSHCNV values for all the channels whose status was displayed.

It occurred to me that there are many other examples of commands where you might want to total up some integer attribute from a set of objects or status records.

  • DISPLAY QLOCAL(SYSTEM.ADMIN.*.EVENT) CURDEPTH
    How many event messages you have
  • DISPLAY CHSTATUS(*) WHERE(RQMNAME EQ MQG2) MSGS
    How many messages have been sent to queue manager MQG2
  • DISPLAY TPSTATUS(‘#’) TYPE(SUB) NUMMSGS
    How many messages have been sent to susbcribers
  • DISPLAY QLOCAL(*) OPPROCS
    How many putting applications are around

Instead of repeating the single line each time with changes to reflect the different command, it might be handy to have a little function that you could just throw a command at and it would do the totaling up for you. For example, you could do something like this:-

func totals(Command,Attribute)
  @total = 0
  foreach(@Command + ' ' + @Attribute)
    @total = @total + eval(@Attribute)
  endfor
  print 'Total of',@Attribute,'for all',@Command,'is',@total
endfunc

And then call it and get the result like so:-

totals("DISPLAY QLOCAL(Q*)","CURDEPTH")

Total of CURDEPTH for all DISPLAY QLOCAL(Q*) is 8

MQSCX functions are just so handy!

DISPLAY DQM for Distributed

If you’re familiar with the IBM MQ for z/OS product, you may have issued the DISPLAY DQM command which gives you the following output:

CSQX830I M901 CSQXRDQM Channel initiator active
CSQX831I M901 CSQXRDQM 8 adapter subtasks started, 8 requested 
CSQX832I M901 CSQXRDQM 5 dispatchers started, 5 requested
CSQX833I M901 CSQXRDQM 0 SSL server subtasks started, 0 requested
CSQX840I M901 CSQXRDQM 5 channels current, maximum 200 
CSQX841I M901 CSQXRDQM 4 channels active, maximum 200, including 0 paused 
CSQX842I M901 CSQXRDQM 0 channels starting, 1 stopped, 0 retrying
CSQX836I M901 CSQXRDQM Maximum channels - TCP/IP 200, LU 6.2 200 
CSQX845I M901 CSQXRDQM TCP/IP system name is TCPIP 
CSQX846I M901 CSQXRDQM TCP/IP listener INDISP=QMGR started, for port 1591 address *
CSQX849I M901 CSQXRDQM LU 6.2 listener INDISP=QMGR not started 

There is no equivalent command for a distributed queue manager, however, you can get most of the same information from various other commands. So we have created an MQSCX script to create an equivalent set of output for a distributed queue manager.

Clearly some of the information simply doesn’t apply to distributed queue managers; for example the number of adapter, dispatcher and SSL Server subtasks. Also the TCP/IP system name doesn’t really have an equivalent on a distributed platform – or at least certainly not one that can be retrieved from the command server. The equivalents of DISPLAY QMGR MAXCHL ACTCHL TCPCHL LU62CHL is to look in the queue manager’s qm.ini file for MaxChannels and MaxActiveChannels on distributed, which is something that cannot work unless you are running the script local to the queue manager.

So the script issues the various commands required to get the information and then prints out a set of equivalent looking lines to give you a similar output:

MQG1 Channel initiator active
MQG1 14 channels current, maximum 400
MQG1 12 channels active, maximum 400, including 0 paused
MQG1 0 channels starting, 1 stopped, 1 retrying
MQG1 TCP/IP listener TCP.LSTR started, for port 1701 address *
MQG1 LU6.2 listener not started

It starts by checking whether the Channel initiator is active, which for most people will be since it gets started automatically by the queue manager these days.

DISPLAY QMSTATUS CHINIT
if (CHINIT = "RUNNING")
  print _qmgr,'Channel initiator active'
endif

Then it looks in the qm.ini file (but only if you’re not connected by a client or via connection). MQSCX can read environment variables just as if they were user variables, so it can make use of the MQ environment variable MQ_DATA_PATH which is setup by setmqenv. The _client system variable is new in MQSCX V9.0.0.

if (!(_client | (_connqmgr != _qmgr)))
  @filename = @MQ_DATA_PATH+"/qmgrs/"+_qmgr+"/qm.ini"
  @hf = fopen(@filename,"r")
  if (@hf)
    while (fgets(@hf,@line) >= 0)

For each line in the qm.ini file it will check for MaxChannels and MaxActiveChannels.

if (findstri(@line, "MaxChannels") > 0)
  @offset = findstr(@line, "=")
  if (@offset > 0)
    @MaxChannelsStr = substr(@line,@offset+1,strlen(@line)-@offset)
    @MaxChannels = eval(@MaxChannelsStr)
  endif
endif

A simple foreach loop allows the script to total up the number of different channel states currently on show. This then allows the various channel status lines in the output to be printed.

Finally the script has another simple foreach loop for listeners which also makes use of the new _numEach system variable to detect if the loop has never been called.

foreach(DISPLAY LSSTATUS(*) ALL WHERE(TRPTYPE EQ TCP))
  print _qmgr, 'TCP/IP listener', LISTENER ,'started, for port', PORT, 'address', IPADDR
endfor
if (_numEach = 0)
  print _qmgr, 'TCP/IP listener not started'
endif

The complete function is available to download in our Example Scripts bundle.


If you’re not a current licence holder, and you’d like to try out MQSCX, please email support@mqgem.com to request a trial licence.