Revision: 2010
http://nagiosplug.svn.sourceforge.net/nagiosplug/?rev=2010&view=rev
Author: tonvoon
Date: 2008-06-02 09:22:35 -0700 (Mon, 02 Jun 2008)
Log Message:
-----------
Optimised pst3 for systems with large number of processes (Duncan Ferguson)
Modified Paths:
--------------
nagiosplug/trunk/NEWS
nagiosplug/trunk/plugins-root/pst3.c
Modified: nagiosplug/trunk/NEWS
===================================================================
--- nagiosplug/trunk/NEWS 2008-06-02 16:21:09 UTC (rev 2009)
+++ nagiosplug/trunk/NEWS 2008-06-02 16:22:35 UTC (rev 2010)
@@ -2,6 +2,7 @@
1.4.?? ??th ??? 200?
Fix Debian bug #460097: check_http --max-age broken (Hilko Bengen)
+ Optimised pst3 for systems with large number of processes (Duncan Ferguson)
Updated Nagios::Plugin to 0.27
1.4.12 27th May 2008
Modified: nagiosplug/trunk/plugins-root/pst3.c
===================================================================
--- nagiosplug/trunk/plugins-root/pst3.c 2008-06-02 16:21:09 UTC (rev 2009)
+++ nagiosplug/trunk/plugins-root/pst3.c 2008-06-02 16:22:35 UTC (rev 2010)
@@ -1,17 +1,37 @@
-/* pst3.c
+/*****************************************************************************
+*
+* pst3
+*
+* License: GPL
+* Copyright (c) 2008 Nagios Plugin Development Team
+*
+* Description:
+*
+* This file contains the pst3 executable. This is a replacement ps command
+* for Solaris to get output which provides a long argument listing, which
+* is not possible with the standard ps command (due to truncation). /usr/ucb/ps
+* also has issues where some fields run into each other.
+*
+* This executable works by reading the kernel memory structures, so needs
+* to be executed as root
*
-* Third version to get process arg info; this time by using
-* a combination of reading the /proc/<pid>/psinfo structures
-* and reading the complete arg vector from kernel memory structures.
-*
-* Developed and tested under Solaris 5.8 (both 32 and 64 bit modes).
-*
-* NOTE: This program must be setuid-root (or run by root) to work!
-*
-* Written: 2005-04-28 R.W.Ingraham
-*/
+* Originally written by R.W.Ingraham
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+*****************************************************************************/
-
#define _KMEMUSER 1
#include <kvm.h>
@@ -37,6 +57,8 @@
#define PROC_DIR "/proc"
#define MAX_PATH 1024
+#define OK 0
+#define FAIL NULL
/*
@@ -59,13 +81,10 @@
* Prototypes
*/
-static int HandleFile (struct dirent *pDent);
-static int HandlePsInfo (char *szPath, psinfo_t *pPsInfo);
-static int GetArgVectors (pid_t pid);
-static void ShowArgVectors (void);
-static void ReleaseArgVectors();
+static int output_info(struct proc *proc_kvm, psinfo_t procinfo,char **proc_argv);
+static psinfo_t get_procinfo(struct proc *proc);
+static int HandleProc(struct proc *proc);
-
/*----------------------------------------------------------------------------*/
int main (int argc, char **argv)
@@ -73,8 +92,9 @@
DIR *pDir;
struct dirent *pDent;
int retcode = 0;
+ struct proc *proc;
+ struct pid pid;
-
/* Set our program name global */
if ((szProg = strrchr(argv[0], '/')) != NULL)
szProg++;
@@ -95,27 +115,29 @@
exit(2);
}
- /* Open the /proc directory */
- if ((pDir = opendir(PROC_DIR)) != NULL)
- {
- /* Display column headings */
- printf("S UID PID PPID VSZ RSS %%CPU COMMAND ARGS\n");
+ /* reset to first proc in list */
+ if(kvm_setproc(kd) == -1) {
+ perror("kvm_setproc");
+ exit(2);
+ }
- /* Zip through all of the process entries */
- while ((pDent = readdir(pDir)) != NULL)
- {
- /* Handle each pid sub-directory */
- HandleFile(pDent);
- }
+ /* Display column headings */
+ printf("%c %5s %5s %5s %6s %6s %4s %s %s\n",
+ 'S',
+ "UID",
+ "PID",
+ "PPID",
+ "VSZ",
+ "RSS",
+ "%CPU",
+ "COMMAND",
+ "ARGS"
+ );
- /* Close the directory */
- closedir(pDir);
+ /* Zip through all of the process entries */
+ while((proc = kvm_nextproc(kd)) != 0) {
+ HandleProc(proc);
}
- else /* ERROR: Failure to open PROC_DIR */
- {
- fprintf(stderr, "%s: Failed to open \"%s\": %s\n", szProg, PROC_DIR, strerror(errno));
- retcode = 3;
- }
/* Close the handle to the running kernel image */
kvm_close(kd);
@@ -125,129 +147,76 @@
/*----------------------------------------------------------------------------*/
-static int HandleFile (struct dirent *pDent)
+static int HandleProc(struct proc *proc)
{
- char szPath[MAX_PATH];
- psinfo_t sPsInfo;
- int fd, len;
- int rc = 0;
+ struct pid pid;
+ struct user *user;
+ psinfo_t procinfo;
+ char **proc_argv = 0;
- /* Skip files beginning with a "." */
- if (pDent->d_name[0] == '.')
- return 0;
-
- /* Cosntruct the path to the psinfo file */
- len = sprintf(szPath, "%s/%s/psinfo", PROC_DIR, pDent->d_name);
-
- /* Open the psinfo file for this pid and print out its arg vectors */
- if ((fd = open(szPath, O_RDONLY)) >= 0)
- {
- /* Read the psinfo struct */
- if ((len = read(fd, &sPsInfo, sizeof(sPsInfo))) != sizeof(sPsInfo))
- {
- rc = errno;
- fprintf(stderr, "%s: Read error of psinfo structure (%d)\n", szPath, len);
- return rc;
- }
-
- /* Close the psinfo file */
- close(fd);
-
- /* Pass psinfo struct to reporting function */
- HandlePsInfo(szPath, &sPsInfo);
+ if(kvm_kread(kd, (unsigned long) proc->p_pidp, (char *) &pid, sizeof pid) == -1) {
+ perror("kvm_read error");
+ exit(2);
}
- else if (errno != ENOENT)
- {
- rc = errno;
- fprintf(stderr, "%s: %s\n", szPath, strerror(errno));
- }
+ proc->p_pidp = &pid;
+ user = kvm_getu(kd, proc);
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int HandlePsInfo (char *szPath, psinfo_t *pPsInfo)
-{
- int retcode;
- char *thisProg;
-
- /* Make sure that the process is still there */
- if ((retcode = GetArgVectors(pPsInfo->pr_pid)) == 0)
- {
- /* We use the program name from the kvm argv[0] instead
- * of pr_fname from the psinfo struct because pr_fname
- * may be truncated.
- *
- * Also, strip-off leading path information.
- */
- if ((thisProg = strrchr(myArgv[0], '/')) != NULL)
- thisProg++;
- else
- thisProg = myArgv[0];
-
- /* Display the ps columns (except for argv) */
- printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ",
- pPsInfo->pr_lwp.pr_sname,
- (int)(pPsInfo->pr_euid),
- (int)(pPsInfo->pr_pid),
- (int)(pPsInfo->pr_ppid),
- (unsigned long)(pPsInfo->pr_size),
- (unsigned long)(pPsInfo->pr_rssize),
- ((float)(pPsInfo->pr_pctcpu) / 0x8000 * 100.0),
- thisProg);
-
- /* Display the arg vectors associated with this pid */
- ShowArgVectors();
-
- /* Release the arg vector buffer memory */
- ReleaseArgVectors();
+ if(kvm_getcmd(kd, proc, user, &proc_argv, NULL) == -1) {
+ return FAIL;
}
- return retcode;
+ procinfo = get_procinfo(proc);
+ return output_info(proc, procinfo, proc_argv);
}
-/*----------------------------------------------------------------------------*/
-
-static int GetArgVectors (pid_t pid)
+static psinfo_t get_procinfo(struct proc *proc)
{
- int retcode = 1;
+ char procpath[MAX_PATH];
+ psinfo_t procinfo;
+ int fd, len;
- /* Get the proc structure for the specified PID */
- if ((pProc = kvm_getproc(kd, pid)) != NULL)
+ sprintf(procpath, "/proc/%d/psinfo", proc->p_pidp->pid_id);
+
+ if ((fd = open(procpath, O_RDONLY)) >= 0)
{
- /* Save a copy of the process' u-area */
- if ((pUser = kvm_getu(kd, pProc)) != NULL)
+ if ((len = read(fd, &procinfo, sizeof(procinfo))) != sizeof(procinfo))
{
- /* Reconstruct the process' argv vector array */
- if (kvm_getcmd(kd, pProc, pUser, &myArgv, NULL) == 0)
- {
- retcode = 0;
- }
+ fprintf(stderr,"%s: Read error of psingo structure (%d)\n", procpath, len);
+ exit(2);
}
+ close(fd);
}
+ return procinfo;
- return retcode;
}
-/*----------------------------------------------------------------------------*/
-
-static void ShowArgVectors (void)
+static int output_info(struct proc *proc_kvm, psinfo_t procinfo, char **proc_argv)
{
+ char *procname;
int i;
- for (i=0; myArgv[i]; i++)
- {
- printf(" %s", myArgv[i]);
+ if((procname = strrchr(proc_argv[0], '/')) != NULL)
+ procname++;
+ else
+ procname = proc_argv[0];
+
+ printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ",
+ procinfo.pr_lwp.pr_sname,
+ (int)(procinfo.pr_euid),
+ (int)proc_kvm->p_pidp->pid_id,
+ (int)proc_kvm->p_ppid,
+ (unsigned long)(procinfo.pr_size),
+ (unsigned long)(procinfo.pr_rssize),
+ ((float)(procinfo.pr_pctcpu) / 0x8000 * 100.0),
+ procname
+ );
+
+ for(i=0;proc_argv[i];i++) {
+ printf(" %s", proc_argv[i]);
}
+
printf("\n");
-}
-/*----------------------------------------------------------------------------*/
-
-static void ReleaseArgVectors()
-{
- /* NOOP */
+ return OK;
}
-/*----------------------------------------------------------------------------*/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.