check_memfree.cpp 4.08 KB
#include "check_memfree.h"

using namespace std;

char *servicename = (char*)"MEMORY";

void getMem(ifstream *file, MEMINFO *meminfo)
{
	meminfo->freeMem = 0;
	meminfo->totalMem = 0;
	string line, field, value;
	getline(*file,line);
	do
	{
		field = line.substr(0,line.find_first_of(':'));
		value = line.substr(line.find_first_of(' '),line.find_last_of(' '));
		if(field == "MemTotal")
		{
			meminfo->totalMem = str2int(value);
		}
		else if(field == "MemFree")
		{
			meminfo->freeMem += str2int(value);
		}
		else if(field == "Buffers")
		{
			meminfo->freeMem += str2int(value);
		}
		else if(field == "Cached")
		{
			meminfo->freeMem += str2int(value);
		}
		getline(*file,line);
	}while(!file->eof());
}

int getNum(ifstream *file)
{
	string numStr = "";
	int num;
	file->ignore(numeric_limits<streamsize>::max(),' ');
	(*file) >> numStr;
	try
	{
		num = str2int(numStr);
	}
	catch(integerConversionException e)
	{
		cout << e.what() << endl;
		exit(3);
	}
	getline(*file,numStr);
	return num;
}

void printVersion()
{
	cout << "check_memfree v" << VERSION << endl << endl;
}

void printHelp(bool longVersion)
{
	if(longVersion)
	{
		printVersion();
		cout << "Check free memory space on local machine." << endl << endl;
		printHelp(false);
		cout << "Options:" << endl;
		cout << " -h" << endl;
		cout << "    Print detailed help screen" << endl;
		cout << " -V" << endl;
		cout << "    Print version information" << endl;
		cout << " -w INTEGER" << endl;
		cout << "    Exit with WARNING status if less than INTEGER bytes of memory space are free" << endl;
		cout << " -w PERCENT%" << endl;
		cout << "    Exit with WARNING status if less than PERCENT of memory space is free" << endl;
		cout << " -c INTEGER" << endl;
		cout << "    Exit with CRITICAL status if less than INTEGER bytes of memory space are free" << endl;
		cout << " -c PERCENT%" << endl;
		cout << "    Exit with CRITCAL status if less than PERCENT of memory space is free" << endl << endl;
		return;
	}
	cout << "Usage: " << endl << "check_memfree [-hV] -w <percent_free>% -c <percent_free>%" << endl << "check_memfree [-hV] -w <bytes_free> -c <bytes_free>" << endl << endl;
}

int main(int argc, char **argv)
{
	struct itimerval timer;
	timer.it_value.tv_sec = 10;
	timer.it_value.tv_usec = 0;
	timer.it_interval.tv_sec = 0;
	timer.it_interval.tv_usec = 0;
	setitimer (ITIMER_VIRTUAL, &timer, 0);

	struct sigaction sa;
	memset (&sa, 0, sizeof (sa));
	sa.sa_handler = &timer_handler;
	sigaction (SIGVTALRM, &sa, 0);

	char *warningFlag = NULL;
	char *criticalFlag = NULL;
	int c;

	while ((c = getopt (argc, argv, "w:c:Vh")) != -1)
	{
		switch(c)
		{
			case 'w':
        			warningFlag = optarg;
        			break;
			case 'c':
       		 		criticalFlag = optarg;
       		 		break;
			case 'V':
				printVersion();
				return 0;
			case 'h':
				printHelp(true);
				return 0;
			case '?':
				printHelp(false);
				return 3;
		}
	}

	if(warningFlag == NULL)
	{
		cout << "Warning limit (-w) wasn't set. Exiting." << endl;
		return 3;
	}
	if(criticalFlag == NULL)
	{
		cout << "Critical limit (-w) wasn't set. Exiting." << endl;
		return 3;
	}

	MEMINFO meminfo;
	ifstream meminfo_file(MEMINFO_FILE);

	getMem(&meminfo_file,&meminfo);

	meminfo_file.close();

	int freeMemMB = meminfo.freeMem / 1024;
	int totalMemMB = meminfo.totalMem / 1024;
	int percFree = ((double)freeMemMB/(double)totalMemMB)*100;

	range warningLimit, criticalLimit;

	try
	{
		warningLimit = parseRange(warningFlag,totalMemMB);
		criticalLimit = parseRange(criticalFlag,totalMemMB);
	}
	catch(rangeException e)
	{
		cout << e.what() << endl;
		exit(3);
	}

	int returnCode;

	cout << servicename;

	if((freeMemMB > criticalLimit.min) && (freeMemMB < criticalLimit.max))
	{
		cout << " CRITICAL";
		returnCode = 2;
	}
	else if((freeMemMB > warningLimit.min) && (freeMemMB < warningLimit.max))
	{
		cout << " WARNING";
		returnCode = 1;
	}
	else
	{
		cout << " OK";
		returnCode = 0;
	}
	cout << " - " << percFree << "% free (" << freeMemMB << " MB out of " << totalMemMB << " MB) |memory=" << freeMemMB << "MB;" << warningLimit.max << ";" << criticalLimit.max << ";" << "0;" << totalMemMB << endl;
	return returnCode;
}