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

using namespace std;

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

int getNum(string cmd)
{
	char buffer[128];
	stringstream sstr;
	FILE* pipe = popen(cmd.c_str(), "r");
	while (!feof(pipe)) 
	{
		if (fgets(buffer, 128, pipe) != NULL)
		{
			sstr.str(sstr.str()+buffer);
		}
	}
	pclose(pipe);
	int num;
	sstr >> num;
	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;
	}

	double freeMem = 0;
	double totalMem = 0;
	double pageSize = 0;

	totalMem = getNum("sysctl hw.physmem | cut -d' ' -f 2") / 1024;
	pageSize = getNum("sysctl hw.pagesize | cut -d' ' -f 2");

	freeMem += getNum("sysctl vm.stats.vm.v_inactive_count | cut -d' ' -f 2") * pageSize;
	freeMem += getNum("sysctl vm.stats.vm.v_cache_count | cut -d' ' -f 2") * pageSize;
	freeMem += getNum("sysctl vm.stats.vm.v_free_count | cut -d' ' -f 2") * pageSize;
	freeMem /= 1024;

	int freeMemMB = freeMem / 1024;
	int totalMemMB = 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;
}