Skip to Content
In the final part of this series of blogs, I’m going to focus on one of the biggest benefits of being able to make RFC calls to an SAP system – well, one of the biggest benefits to a system administrator, that is. And that would be alerting. I’m only going to provide rather basic functionality here because, to be honest, an instructional course in perl is not the point of this blog, and there is so much you can do with it, I would never finish if that were my intent (nor am I the right person to be doing that!). In fact, I’m not even scratching the surface of what capabilities perl has to offer to extend the functionality of this script.

My goal here is simply to open the eyes of many system administrators that don’t typically think of doing this on their own. As I alluded to previously, so many skilled admins don’t even think about writing their own programs to administer their systems nowadays. Third-party tools are so advanced, and so feature-packed, that it almost seems unnecessary. But what if you don’t have a budget to purchase those tools? What if your needs are simple, and the costs of the tools are simply not justified?

It is in these cases that I hope to at least open some eyes to the fact that there is another way. A simple way. Perhaps an even more powerful way. But certainly a way that can get you most, if not all, of what you need, with minimal effort. And if you want to take it just a bit further, there are an infinite amount of resources on the Internet to guide you in doing so.

So let’s jump in.

In the previous blogs in this series, we developed a script that would read the system log from all servers in a system. Now, we’ll add the ability to search the system log for specific errors or messages, and alert on these.

The first change to the Perl and SAP Adventures, Part 3 is to add the text we want to search for. Typically, I would do this in an external config file. I prefer, for those scripts I run in production, not to require anyone to modify the script itself to be able to add to its list of monitored items. To keep it simple here, however, I’m doing this within the script itself:

my @searchtext = ('Communication error', 'Error in TemSe Management', 'session.*deleted');

In this line, we’re defining 3 terms to search for. The first two are obvious. The third simply uses a `.*’ as a wildcard to represent 0 or more characters between the words `session’ and `deleted’. There is so much more that you can do with pattern matching in perl; these are just some basics just to get started with.

Next, you’ll notice that I’m modifying the load_config instruction a bit.

SAPNW::Rfc->load_config('rqa.yml');

I’m doing this so that you can see how to change the default `sap.yml’ to use a file by another name instead. In case you want to, for example, use the same script for multiple systems, you would simply define each system connection in a different .yml file, and pass that in here, either with the text I have above, or with a variable such as:

my $ymlfile = 'rqa.yml';
SAPNW::Rfc->load_config($ymlfile);

In the meat of the script, actually pulling back the system log, is where we’ll add the logic to search (case-insensitively) for our text to alert on:

foreach my $row (@{$slr->SYSLOG_TBL}) {                 # do this for each individual line of the system log,
    for my $x (0 .. $#searchtext) {                     # go through each item in the searchtext array defined above
      if ($row->{'LINE'} =~ m/$searchtext[$x]/i) {     # does this item in searchtext exist in this line from the system log?
            $dumptext .= trim($row->{'LINE'})." ";     # if so, add this line from the system log to the $dumptext var
        }
    }                                                   # go to the next item in @searchtext or, if that's all of them,
}                                                       # then go to the next line of the system log and start again

Pretty simple, right?  Now, on to alerting…

Once the previous bit of code has added all of the relevant lines to the $dumptext variable, then we check to see if $dumptext has anything in it. If so, we’ll send an alert. If not, then we’ll just end the script.

if ($dumptext) {                                                     # If we've put any data in $dumptext, then send the alert 
    my $sender;
    my $emailtext="Attention: the following critical errors have been found in the system log: ";   # intro in email body
    ref ($sender = new Mail::Sender({from => goofy@customer.com"})) # instantiate new mail item, define from address
                       || die ("$Mail::Sender::Error ");            # exit the script if an error creating the new mail item
    (ref ($sender->MailMsg({to => "basis_team@customer.com",        # who to send the alert to
                subject => "Email alert from perl",                  # subject line
                msg => "$emailtext $dumptext "}))                  # add intro line, system log lines in $dumptext
                || die ("$Mail::Sender::Error "));                  # exit the script if we get an error sending mail
}

Of course, the previous bit of code assumes you’ve got the Mail::Sender module installed.  If not, you can download it from CPAN, or, if you use the CPAN module to install modules, then you can install it with:

$] perl -MCPAN -e shell 
cpan> install Mail::Sender

Here’s a sample of an email that was sent from this script (I ran this with the same script, except modified the from/to times to search a month of the system log, just so I would have some data to show in the email):

From: Goofy [mailto:goofy@customer.com] 
Sent: Tuesday, July 07, 2009 2:19 PM
To: Basis Team
Subject: Email alert from perl

Attention: the following errors have been found in the system log:


|18:09:12|apsrv002_RQA_00|USER001    |        |        |R4 |9|Communication error, CPIC return code 017, SAP return code 731   |
|00:32:05|apsrv019_RQA_00|USER002    |RSPO1041|        |F7 |1|Error in TemSe Management                                        |
|00:32:06|apsrv019_RQA_00|USER002    |RSPO1041|        |F7 |1|Error in TemSe Management                                        |
|00:32:06|apsrv019_RQA_00|USER002    |RSPO1041|        |F7 |1|Error in TemSe Management                                        |
|00:32:06|apsrv019_RQA_00|USER002    |RSPO1041|        |F7 |1|Error in TemSe Management                                        |
|00:32:06|apsrv019_RQA_00|USER002    |RSPO1041|        |F7 |1|Error in TemSe Management                                        |
|00:32:11|apsrv019_RQA_00|USER002    |RSPO1041|        |F7 |1|Error in TemSe Management                                        |
|09:03:48|apsrv019_RQA_00|USER019    |SAPMHTTP|        |R2 |G|HTTP/RFC session has been deleted following timeout              |
|00:12:19|apsrv720_RQA_00|USER002    |SAPMHTTP|        |R2 |G|HTTP/RFC session has been deleted following timeout              |
|16:38:07|apsrv235_RQA_00|USER001    |SAPMPZ02|        |R2 |G|HTTP/RFC session has been deleted following timeout              |
|18:04:49|apsrv722_RQA_00|USER029    |        |        |R4 |9|Communication error, CPIC return code 020, SAP return code 223   |
|18:04:49|apsrv722_RQA_00|USER029    |        |        |R4 |9|Communication error, CPIC return code 020, SAP return code 223   |
|18:04:49|apsrv722_RQA_00|USER029    |        |        |R4 |9|Communication error, CPIC return code 020, SAP return code 223   |
|11:32:31|apsrv722_RQA_00|USER029    |        |        |R4 |9|Communication error, CPIC return code 020, SAP return code 223   |
|11:39:04|apsrv722_RQA_00|USER011    |SAPMYWDW|        |R2 |G|HTTP/RFC session has been deleted following timeout              |
|15:23:05|apsrv722_RQA_00|USER008    |RSWNWIEX|        |R2 |G|HTTP/RFC session has been deleted following timeout              |
|18:04:02|apsrv723_RQA_00|USER029    |        |        |R4 |9|Communication error, CPIC return code 020, SAP return code 223   |
|18:07:09|apsrv723_RQA_00|USER029    |        |        |R4 |9|Communication error, CPIC return code 020, SAP return code 223   |
|18:07:09|apsrv723_RQA_00|USER029    |        |        |R4 |9|Communication error, CPIC return code 020, SAP return code 223   |
|15:47:48|apsrv724_RQA_00|USER006    |        |        |R4 |9|Communication error, CPIC return code 020, SAP return code 223   |
|15:47:48|apsrv724_RQA_00|USER029    |        |        |R4 |9|Communication error, CPIC return code 020, SAP return code 223   |
|15:47:48|apsrv724_RQA_00|USER029    |        |        |R4 |9|Communication error, CPIC return code 020, SAP return code 223   |
|18:05:17|apsrv724_RQA_00|USER029    |        |        |R4 |9|Communication error, CPIC return code 020, SAP return code 223   |
|18:05:17|apsrv724_RQA_00|USER029    |        |        |R4 |9|Communication error, CPIC return code 020, SAP return code 223   |

And here’s the entire script:

#!/usr/bin/perl -w
use strict;
use sapnwrfc;
use Mail::Sender;
my $srvcnt = 0;
my @server = ();
my $dumptext;
my @searchtext = ('Communication error', 'Error in TemSe Management', 'session.*deleted');
SAPNW::Rfc->load_config('rqa.yml');
my $rfc = SAPNW::Rfc->rfc_connect;

### Enumerate the list of available servers
my $rcb = $rfc->function_lookup("TH_SERVER_LIST");
my $tsl = $rcb->create_function_call;
$tsl->invoke;
foreach my $row (@{$tsl->LIST}) {
    $server[$srvcnt]=trim($row->{'NAME'});
    $srvcnt ++;
}

### Log on to the XMB Interface
my $rca = $rfc->function_lookup("SXMI_LOGON");
my $xln = $rca->create_function_call;
$xln->EXTCOMPANY('TWDC');
$xln->EXTPRODUCT('RFCTEST');
$xln->INTERFACE('XMB');
$xln->parameter('VERSION')->value('0.1');
$xln->invoke;

### For each app server, read its system log, check for string matches
for my $x (0 .. $#server) {
    my $rcc = $rfc->function_lookup("SXMI_XMB_SYSLOG_READ");
    my $slr = $rcc->create_function_call;
    $slr->SERVER_NAME($server[$x]);
    $slr->EXTERNAL_USER_NAME('GOOFY');
    $slr->invoke;

    foreach my $row (@{$slr->SYSLOG_TBL}) {
        for my $x (0 .. $#searchtext) {
            if ($row->{'LINE'} =~ m/$searchtext[$x]/i) {
                $dumptext .= trim($row->{'LINE'})." ";
            }
        }
    }
}

### Log off of the XMB Interface
my $rcd = $rfc->function_lookup("SXMI_LOGOFF");
my $xlf = $rcd->create_function_call;
$xlf->INTERFACE('XMB');
$xlf->invoke;

$rfc->disconnect();

### send alert
if ($dumptext) {
    my $sender;
    my $emailtext="Attention: the following critical errors have been found in the system log: ";
    ref ($sender = new Mail::Sender({from => "goofy@customer.com"})) || die ("$Mail::Sender::Error ");
    (ref ($sender->MailMsg({to => "basis_team@customer.com",
                subject => "Email alert from perl",
                msg => "$emailtext $dumptext "}))
                || die ("$Mail::Sender::Error "));
}

### trim leading and trailing spaces
sub trim {
    my @OUT = @_;
    for (@OUT) {
        s/^s+//;
        s/s+$//;
    }
    return wantarray ? @OUT : $OUT[0];
}

And there you have it. I hope this was helpful. I plan on adding most of the technical bits of these blogs to the wiki as well, and, as time permits, even adding some more scripts.

To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

  1. Mingzuo Shen
    During the migration process problems have been reported for this blog. The blog content may look corrupt due to not supported HTML code on this platform. Please adjust the blog content manually before moving it to an official community.
    (0) 

Leave a Reply