Using PROC IOMOPERATE to list and stop your SAS sessions

36

If you're a SAS administrator, you probably know that you can use SAS Management Console to view active SAS processes. These are the SAS sessions that have been spawned by clients such as SAS Enterprise Guide or SAS Add-In for Microsoft Office, or those running SAS stored processes. But did you know that you can generate a list of these processes with SAS code? It's possible with the IOMOPERATE procedure.

To use PROC IOMOPERATE, you need to know the connection information for the SAS Object Spawner: the host, port, and credentials that are valid for connecting to the Object Spawner operator port. You plug this information into a URI scheme like the following:

iom://HOSTNAME:PORT;bridge;user=USERID,pass=PASSWORD

Here's an example:

iom://myserver.company.com:8581;bridge;user=sasadm@saspw,pass=Secret01

Are you squeamish about clear-text passwords? Good for you! You can also use PROC PWENCODE to obscure the password and replace its value in the URI, like this:

iom://myserver.company.com:8581;bridge;user=sasadm@saspw,
 pass={SAS002}BA7B9D0645FD56CB1E51982946B26573

Getting useful information from PROC IOMOPERATE is an iterative process. First, you use the LIST SPAWNED command to show all of the spawned SAS processes:

%let connection=
  'iom://myserver.company.com:8581;bridge;user=sasadm@saspw,pass=Secret01';
 
/* Get a list of processes */
proc iomoperate uri=&connection.;
    list spawned out=spawned;
quit;

Example output:
listspawned
You can retrieve more details about each process by running subsequent IOMOPERATE steps with the LIST ATTRS command. This can get tedious if you have a long list of spawned sessions. I've wrapped the whole shebang into a SAS program that discovers the processes and iterates through the list for you.

%let connection=
 'iom://myserver.company.com:8581;bridge;user=sasadm@saspw,pass=Secret01';
 
/* Get a list of processes */
proc iomoperate uri=&connection.;
    list spawned out=spawned;
quit;
 
/* Use DOSUBL to submit a PROC IOMOPERATE step for   */
/* each SAS process to get details                   */
/* Then use PROC TRANSPOSE to get a row-wise version */
data _null_;
    set spawned;
    /* number each output data set */
    /* for easier appending later  */
    /* TPIDS001, TPIDS002, etc.    */
    length y $ 3;
    y = put(_n_,z3.);
    x = dosubl("
    proc iomoperate uri=&connection. launched='" || serverid || "';
    list attrs cat='Information' out=pids" || y || ";
    quit;
    data pids" || y || ";
    set pids" || y || ";
    length sname $30;
    sname = substr(name,find(name,'.')+1);
    run;
 
    proc transpose data=work.pids" || y || "
    out=work.tpids" || y || "
    ;
    id sname;
    var value;
    run;
    ");
run;
 
/* Append all transposed details together */
data allpids;
    set tpids:;
    /* calculate a legit datetime value */
    length StartTime 8;
    format StartTime datetime20.;
    starttime = input(UpTime,anydtdtm19.);
run;
 
/* Clean up */
proc datasets lib=work nolist;
delete tpids:;
delete spawned;
quit;

The output details include "up time" (when the process was launched), the process ID (a.k.a. PID), the owner account, the SAS version, and more. Here's a snippet of some example output:
detailspawn

You can use this information to stop a process, if you want. That's right: from a SAS program, you can end any (or all) of the spawned SAS processes within your SAS environment. That's a handy addition to the SAS administrator toolbox, though it should be used carefully! If you stop a process that's in active use, an unsuspecting SAS Enterprise Guide user might lose work. And he won't thank you for that!

To end (kill) a SAS process, you need to reference it by its unique identifier. In this case, that's not the PID -- it's the UUID that the LIST ATTRS (or ATTRIBUTES) command provided. Here's an example of the STOP command:

/* To STOP a process */
    proc iomoperate uri=&connection.;                                  
        STOP spawned server 
             id="03401A2E-F686-43A4-8872-F3438D272973"; 
    quit;                                                             
/* ID = value is the UniqueIdentifier (UUID)      */
/*  Not the process ID (PID)                      */

It seemed to me that this entire process could be made easier with a SAS Enterprise Guide custom task, so I've built one! I'll share the details of that within my next blog post.

Share

About Author

Chris Hemedinger

Director, SAS User Engagement

+Chris Hemedinger is the Director of SAS User Engagement, which includes our SAS Communities and SAS User Groups. Since 1993, Chris has worked for SAS as an author, a software developer, an R&D manager and a consultant. Inexplicably, Chris is still coasting on the limited fame he earned as an author of SAS For Dummies

36 Comments

  1. Nice tool, I agree about the password, it would be nice to be able to access the authdomain instead of encoding the password. I could'nt logging the way you did it I had some credential problem with your method so I did it this way:
    PROC IOMOPERATE;
    CONNECT host='server'
    port=8581
    user='user'
    pass='encodeedpassword'
    servertype=OBJECTSPAWNER;
    list spawned out=spawned;
    QUIT;

    • Chris Hemedinger
      Chris Hemedinger on

      Glad you got it! I was working from an internal example that used the URI scheme, so I didn't even look at the "classic" method of the CONNECT statement.

  2. Thanks, Chris.
    It's a great post, again.

    And, when I ran the code, I got EMPTY output, even I know someone is running SAS EG.
    And, it's the same in SAS MC -> Server Manager.

    Do you know why?

    Many thanks in advance.

    BR./Edward

    • Chris Hemedinger
      Chris Hemedinger on

      Edward,

      Couple of things to check. Is the EG user connected to a spawned SAS session (like SASApp) -- not a local SAS? Local SAS sessions won't show up in the list. Also, are you using credentials that have permissions to see this information from the Object Spawner? I do my testing with a SAS administrator account.

      • Hi, Chris.
        I probably know what is going on. My users are using SAS EG to connect to SAS Metadata server via port 8561.
        Maybe I should update the port number and below line
        list spawned out=spawned;
        Do you think?

        BR./Edward

        • Chris Hemedinger
          Chris Hemedinger on

          PROC IOMOPERATE has to connect to the Object Spawner operator port, which is 8581 in a default configuration. You can verify this in your environment with a program like this (run from EG while connected to a metadata server):

          filename query temp; filename result temp; data _null_; file query; input; put _infile_ ' '; datalines; <GetMetadataObjects> <Reposid>$METAREPOSITORY</Reposid> <Type>TCPIPConnection</Type> <Objects/> <NS>SAS</NS> <Flags>2440</Flags> <Options> <XMLSelect search="*[@ApplicationProtocol='Operator']"/> </Options> </GetMetadataObjects> ;; run; proc metadata in=query out=result; run; /* show result in log */ data _null_; infile result; input; list; run;

  3. Pingback: A custom task to list and stop your SAS sessions - The SAS Dummy

  4. Hi,

    Related with this post, do you know how can I show the user who launched the Spawner? I mean, the user that appears in:
    SAS Management Console -> Server Manager -> SASApp -> SASApp - Logical Workspace Server -> SASApp - Workspace Server -> nameoftheserver -> (Right clic + connect) -> PID XXXXX
    And if you click over PID, you can see the user.

    Thank you very much in advance,

    Oscar

  5. Hey Chris! Was on a call with you in the afternoon last Friday. Tried the Custom Task but it must take a while to run and canceled it after about ten minutes. Then tried the above option with the PROC IOMOperate and it shows 13 total processes. Then the output is only the statistics for the first process. Probably not understanding the instructions completely but each process has to be run manually in the Proc in the dosubl function and you change y each time for each subsequent process in the null data step or is something else being missed. Not sure exactly what part of the code needs to be changed 12 more times for each process currently running to show the statistics for all processes. Please reply when you have a chance.

    Thanks!

    • Chris Hemedinger
      Chris Hemedinger on

      Bob - what version of SAS? DOSUBL works best with SAS 9.3M2 or later. It was in earlier 9.3 releases, but the behavior wasn't quite right...

  6. Thanks Chris for this.

    I am looking to get the Date, PID and the username with which I can work out,how long the session has been active and possibly set up an email alert to the users saying your session has been active since 10 days or so. How do I get them ?

    We have audit logging switched on and I am able to get the details of all user activity but it doesn't seem to indicate if a session is active so there is no way to know if the activity is for an active session or something that is old if you know what I mean. I do know that if I parse through Object spawner I can get this information, but I don't want to go through that effort if something simpler is already available.

  7. Hello Chris
    Someone directed me to this post to try and solve an occasional issue I'm encountering, but it doesn't seem to fit the bill quite. I wonder if there are any other options?
    I've got a few users set up to use Schedule Manager to schedule regular jobs. This is using operating system scheduling (Windows). Occasionally one of them has a scheduled job which overruns and so they want to kill it. If I'm around I can do that for them in a RDP session but they don't have that kind of direct access to the server. It was suggested that your code above might be the answer. However, because the jobs aren't started by the spawner, they don't get captured by PROC IOMOPERATE.
    Do you have any thoughts about how we might tackle this?
    Thanks

    • Chris Hemedinger
      Chris Hemedinger on

      Hi Nigel,

      You're correct -- PROC IOMOPERATE doesn't have a role here. On UNIX we would use the "ps" command to find processes, and "kill" to end the runaway process with the process ID (pid). On Windows we have the TASKLIST and TASKKILL commands to do the same thing. These each have options for remote computers as well -- as long as the end user has enough permission to see their own processes on the remote machine. I found this old post from Microsoft that might help.

      • Thanks Chris. Unfortunately our users aren't able to see their processes on the remote machine. Our workstations are heavily locked down, so that ordinary users are unable to open cmd.exe (or Powershell). So it looks like it's going to be down to me or my sysadmin colleagues.

  8. How do I get the Application Name that is invoking the Worksapce server Session?
    Without the application name, its hard to capture the session details among multiple PID's per user.

    • Chris Hemedinger
      Chris Hemedinger on

      I don't think you can get that from this code. I do think the app name appears in the Object Spawner log, but I don't think that attribute appears in the IOMOPERATE output.

      • Thanks Chris! I currently don't see any programmatic way of accessing the Object Spawner logs through any SAS PROCs including IOMOPERATE. Any suggestions or product improvements in the pipeline that would help in this regard?

        • Chris Hemedinger
          Chris Hemedinger on

          To be honest, probably not. The architecture of the SAS 9 environment (metadata, workspace, spawner, etc.) is very stable and mature, and not undergoing many changes. More attention is going to evolving the SAS Viya architecture and its APIs and cloud-native approach. In that world, CLIs and APIs do/will allow great control, in concert with the native capabilities of cloud providers.

  9. Thanks Chris,

    Searched the documentation a bit more and found that I could use the list log filter and out option to have the messages sent to a SAS dataset.
    Will filter out the APPNAME from the spawner log to get the session PID + APPNAME.

    Sample code below:
    proc iomoperate uri=&myConnection.;
    list log filter="start=06FEB2020:02:00:00" OUT=TEST;
    quit;

    Very excited to move to Viya !

  10. Hello,

    Is there any way instead of copy and pasting the ID multiple times, we can simply do it one go. If anyone it will great help, I am new to SAS.

    Thanks In Advance.

    • Chris Hemedinger
      Chris Hemedinger on

      To "kill" a session? Yes, you could write SAS code that iterates through and does this if needed. Since the PIDs and their UniqueIdentifier values are output as a data set, you could use DATA step and CALL EXECUTE to iterate and issue the "STOP" command for each.

      • Thanks Chris! I used Below code and it worked. I hope we have something for base SAS connection.

        %macro tests(UniqueIdentifier);
        proc iomoperate uri=&connection.;
        STOP spawned server
        id="&UniqueIdentifier";
        quit;
        %mend;

        data _null_;
        set allpids;
        put UniqueIdentifier;
        call execute ('%tests('||UniqueIdentifier||')');
        run;

  11. Victor Andruskevitch on

    Chris,
    I am trying to get your code working in our Viya environment. I connecting to the SPRE server on port 8581. Each time I getting a ERROR: IOM context initialization failed.message. Any suggestions?

    • Chris Hemedinger
      Chris Hemedinger on

      Hi Victor, I'm not sure what the standard operator port is for object spawner in Viya. Also, I know that when you connect EG to SAS Viya you need some additional certificates in place -- not sure if that's a factor. SAS Metadata Server isn't present, so object spawner is likely configured "old school" with a config file setup...but I'm not familiar with it. Come to think of it, I'm not sure how much of PROC IOMOPERATE is available in SAS Viya -- it's documented only in the context of SAS 9.4 Admin Guide.

  12. Hello
    Excellent blog.
    On one server there are on average 60-65 SAS processes running.
    I added the custom task and it does it looks like it is working.
    I ran the code above and saw that the second step using dosubl function cannot go beyond creating TPID57 dataset. When this point is reached it keeps running.
    Are there any limitations to this?

    • Chris Hemedinger
      Chris Hemedinger on

      I'm not sure why you would hit this limit. Another approach (instead of DOSUBL) would be to write this SAS code to a file and then %include that file for everything to run in series for each spawned session.

      • Hi, Chris,

        I have the same problem, this is the message that is generated after the execution, please if you could help me with the solution you mention because I am not very expert on the topic.

        NOTE: There were 27 observations read from the data set WORK.PIDS001.
        NOTE: The data set WORK.TPIDS001 has 1 observations and 28 variables.
        NOTE: PROCEDURE TRANSPOSE used (Total process time):
        real time 0.02 seconds
        cpu time 0.00 seconds

        1 The SAS System 09:53 Monday, February 22, 2021

        NOTE: The CONNECT command completed.
        ERROR: Requested function is not implemented.
        ERROR: Unsupported function
        ERROR: The LIST ATTRIBUTES command failed.
        NOTE: The SAS System stopped processing this step because of errors.

        Thanks.

        • Chris Hemedinger
          Chris Hemedinger on

          Hi, I'm not sure what's happening in your case. Note that you do need to connect using credentials that have enough admin rights to see and control the running processes. Are you doing that?

          • Albert Ingan on

            Hi Chris,

            I encounter the same error with Daniel which says "ERROR: Unsupported function". I am running the code in our 2 SAS servers, it was running fine until recently the code in 1 server encountered the error while the other one it runs without error.

            Upon splitting the code, the error is caused by the 'LIST ATTRS'. I am not familiar on how the code shows all the details of the process as I cannot also found the command in SAS documentation.

            Can you suggest an alternative to "LIST ATTRS" that I can use ?

            Thanks.

  13. Hi Chris,

    first of all, thank you for posting this very helpful piece of code!
    When running your code in our environment, I noticed, that the server time, that is captured in the "IOM.UpTime" Information has an offset of two hours, ie. it lags 2 hours behind. This is also true, when running

    %PUT &SYSTIME;

    in SAS Enterprise Guid, which leads me to the conclusion, that somewhere in our configuration files the time zone must be misconfigured

    Do you happen to know, where to look up the (object spawner) server time configuration?

    • Chris Hemedinger
      Chris Hemedinger on

      Check PROC OPTIONS GROUP=LANGUAGECONTROL to review the TIMEZONE and LOCALE system options. These values will help determine the timezone offset you're seeing.

Back to Top