If you need to run a Unix command on a remote server with a LoadRunner script (running on Windows), then there is a neat program called plink that you will find very useful.
If you use any variety of Unix, you will probably already by using PuTTY; well plink is is distributed with PuTTY, and allows you to run remote Unix commands from your DOS prompt.
In this example, I have used it to collect disk I/O metrics from a remote Solaris server.
You may need to refer to some background material for the different components that are used for this example.
- Solaris Tips
- AWK
- Running command-line programs from LoadRunner
To capture the %busy metric for each disk, I can run iostat -xc. This gives the following output:
extended device statistics cpu
device r/s w/s kr/s kw/s wait actv svc_t %w %b us sy wt id
md0 0.5 0.6 8.5 0.8 0.0 0.0 19.9 0 0 1 1 0 98
md1 6.3 6.8 50.3 54.5 0.0 0.3 24.0 0 0
md3 0.2 0.7 12.7 12.6 0.0 0.0 11.0 0 1
md5 0.0 0.0 2.7 0.3 0.0 0.0 8.0 0 0
md6 0.0 0.0 0.0 0.0 0.0 0.0 3.6 0 0
md10 0.3 0.6 4.2 0.8 0.0 0.0 21.3 0 0
md11 3.1 6.8 25.1 54.5 0.0 0.3 25.6 0 0
md13 0.1 0.7 6.4 12.6 0.0 0.0 8.7 0 0
Using AWK to just grab the device name and the %b column can be done by running iostat -xc | awk ‘NR >2 {print $1, $9}’, which gives:
md0 0
md1 0
md3 1
md5 0
md6 0
md10 0
md11 0
md13 0
Putting this in a LoadRunner script that will save the %b value for each device using lr_user_data_point() looks like this:
/*
* This script retrieves Disk IO stats from a Solaris server and plots them in the Controller using lr_user_data_point().
*/
#define BUFFER_SIZE 10240 // 10 KB
extern char* strtok(char *token, const char *delimiter); // Explicit declaration required for functions that do not return an int.
Action()
{
long fp; // file/stream pointer
int count; // number of characters that have been read from the stream.
char buffer[BUFFER_SIZE]; // allocate memory for the output of the command.
char * row_token; // for each row in the output of the command.
char field_name[100]; // for the first column in the row.
int field_value; // for the second column in the row.
char lrudp_name[100]; // buffer to hold the LR user data point name.
int rc; // return code for sscanf.
lr_start_transaction("Monitor Disk IO");
// The command we want to run is: plink -ssh -l username -pw password hostname command
lr_save_string("stuart", "UserName");
lr_save_string("asdf7890", "Password");
lr_save_string("sdb526.sysdomain.local", "Server");
lr_save_string("iostat -xc | awk 'NR >2 {print $1, $10}'", "Command"); // run iostat, and retrieve the "device" and "%b" column from the output.
lr_save_string(lr_eval_string("C:\\Progra~1\\PuTTY\\plink -ssh -l {UserName} -pw {Password} {Server} \"{Command}\" 2>&1 0< nul:"), "CompleteCommand"); // Note: plink refuses to work without stdin redirected
fp = popen(lr_eval_string("{CompleteCommand}"), "r");
if (fp == NULL) {
lr_error_message("Error opening stream.");
return -1;
}
count = fread(buffer, sizeof(char), BUFFER_SIZE, fp); // read up to 10KB
if (feof(fp) == 0) {
lr_error_message("Did not reach the end of the input stream when reading. Try increasing BUFFER_SIZE.");
return -1;
}
if (ferror(fp)) {
lr_error_message ("I/O error during read.");
return -1;
}
if (count == 0) {
lr_error_message("Something went wrong when running command. No output returned.");
return -1;
}
buffer[count] = NULL;
/*
The command should return data formatted like this:
md0 0
md1 0
md3 1
md5 0
md6 0
md10 0
md11 0
md13 0
Iterate through each row, and save the name and value.
*/
row_token = (char*) strtok(buffer, "\n"); // Split the buffer at each newline character
if (row_token == NULL) {
lr_error_message ("Something went wrong. No token found");
return -1;
}
while (row_token != NULL) { // While there are still rows in the buffer...
rc = sscanf(row_token, "%s %d", field_name, &field_value); // Grab the field name and value.
if (rc != 2) {
lr_error_message("Incorrect number of items read from the row.");
return -1;
}
// Create a user data point, so this value can be graphed in the LoadRunner Controller (and in LoadRunner Analysis).
sprintf(lrudp_name, "disk_busy_%s", field_name);
lr_user_data_point(lrudp_name, field_value);
row_token = (char*) strtok(NULL, "\n");
}
/*
Output will be
Notify: Data Point "disk_busy_md0" value = 0.0000.
Notify: Data Point "disk_busy_md1" value = 0.0000.
Notify: Data Point "disk_busy_md3" value = 1.0000.
Notify: Data Point "disk_busy_md5" value = 0.0000.
Notify: Data Point "disk_busy_md6" value = 0.0000.
Notify: Data Point "disk_busy_md10" value = 0.0000.
Notify: Data Point "disk_busy_md11" value = 0.0000.
Notify: Data Point "disk_busy_md13" value = 0.0000.
*/
pclose(fp);
lr_end_transaction("Monitor Disk IO", LR_AUTO);
return 0;
}
I hope you find this useful - both for the general concept of using LoadRunner to invoke commands (or shell scripts) on a remote Unix host and retrieve the output, and for the ability to monitor disk IO on Solaris without using SiteScope.
16 Comments
Comments are closed.
Note that the first time you connect to a server using plink, you are likely to get a message like this:
…and you will have to add the key to the cache before you can run plink from LoadRunner.
Another hot tip:
If you use this script for monitoring, run it from a separate load generator, rather than from your Controller, because every time the DOS command is invoked, it briefly pops up an annoying cmd.exe window.
But how I will connect with LoadRunner? Can you describe a more please.
Hi,
Great article..Am trying this out now.
But how do i add the key to server cache ? From LoadRunner or some other means…
Hi,
I am using PuTTy for running UNIX Commonds.The actions I do regularly are :
1.Open PuTTy , give Host , Port and Protocal informtaion
2.Login using UserID & Password…
3. Goto Prticular folder and ececute some scripts in UNIX.
4.The scripts need to be executed sequentially , preferably one by one…
5.Monitor Server performance
I never automated UNIX commonds by PuTTy using LoadRunner,could you help me..
My email id :ilusuresh236@yahoo.com
Regards,
Suresh Kolli
00447890996950
Stuart,
This is a wonderful solution to folk who wish to capture the server vitals while performing load tests without the need to login to unix servers. However from my experience(call me bad coder) of using custom code generously within LR scripts, would eventually lead to memory access violation errors which are annoying to troubleshoot. Should try writing the statistics captured to file using file I/O operations in C. Any comments!
Thanks for sharing this info though!
Rgds,
-AJ
Please suggest any suitable tool for the load testing of Flex based web application?
Hello Stuart,
Thanks for such informative post.
It gives a good guidance in initiating Unix implementation with LR.
We are in a middle of a situation where we would require your guidance. The performance testing of an application based on Unix platform is to be done. The application is deployed on Unix servers & does not have any Web GUI.
I have no clue from where to initiate with the process. How to record such applications with LR? What protocol should be used? How would Client-Server request look like?
It would be highly appreciated if you can guide us on the same, since the work needs to be started soon. It would also be great if, if its possible for you to provide one such recorded sample script.
Thanks in advance
Vishal Saxena
Hi, Stuart. Nice to see your instruction on how to run UNIX command using LR controller under windows. I tried to use LR agent to run a LR script that calls system() function to run a UNIX command, and when using mdrv -usr *.usr, all seems ok. The transaction can pass. However, when I using LR controller under WINDOWS to run the compiled script under $M_LROOT/bin the transaction failed. I used the “Not to use RSH” option. Do you think I should use RSH instead? Any suggestions? Thank you in advance.
It sounds like you are running your vusers from an agent on a Linux/Unix load generator.
The example above runs the Unix command remotely from a Windows load generator.
Unfortunately I am not sure what the problem might be in your case.
On a side-note, I would not recommend that you use Unix/Linux-based load generators for LoadRunner.
Hi Stuart,
After following your steps to execute remote Unix commands I’m getting the below error.
“RVM is not a function, selecting rubies with ‘rvm use …’ will not work.
You need to change your terminal emulator preferences to allow login shell.
Sometimes it is required to use `/bin/bash –login` as the command.”
Also suggest me what I should do to execute series(at least 4) of commands in a single session…
Thank You
Hi
When I executed the script with my server details. The buffer stores only “avg-cpu:”.
Due to this, the script throws error from line 71.
But when I run the formed command manually, the value is:
avg-cpu:
0.67
Am I missing something here?
Hi Stuart,
For SFTP in load runner where to add Private Key so that from load runner i can connect multiple sessions for the user.For me in VUGEN am unable to upload and download but from controller am getting authentication errors. Please help in this regard.
Thanks,
Dixit
Hi Sturat,
I have similar requirement. We are using HP BSM and would like to develop the VuGen script to monitor the Heap usage and fail the transactions like “lr_end_transaction(“Heap_Space_Is_Low”,LR_FAIL)’…..so that each time this script runs, we can get an alert. Is this the right way of doing it if we want to do it from BSM tool? Thanks in advance.
Hi Stuart,
I am trying to connect to my servers using putty by it also needs a certificte to be added to connect to those aws servers. How can i implement that
Hi Stuart,
I am trying to connect to my servers using putty by it also needs a certificte to be added to connect to those aws servers. How can i implement that