summaryrefslogtreecommitdiffstats
path: root/plugins-root/pst3.c
diff options
context:
space:
mode:
authorTon Voon <tonvoon@users.sourceforge.net>2008-06-02 16:22:35 (GMT)
committerTon Voon <tonvoon@users.sourceforge.net>2008-06-02 16:22:35 (GMT)
commit5c3d4aea27de408cb7b04f5aab83558efbf841f4 (patch)
tree8f64706a701b1cde7c64772dd98a4148a305e251 /plugins-root/pst3.c
parent0cbac3382a9e3fb87eb8e6525a13fbb0cc8e4dde (diff)
downloadmonitoring-plugins-5c3d4aea27de408cb7b04f5aab83558efbf841f4.tar.gz
Optimised pst3 for systems with large number of processes (Duncan Ferguson)
git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@2010 f882894a-f735-0410-b71e-b25c423dba1c
Diffstat (limited to 'plugins-root/pst3.c')
-rw-r--r--plugins-root/pst3.c249
1 files changed, 109 insertions, 140 deletions
diff --git a/plugins-root/pst3.c b/plugins-root/pst3.c
index 5b0e9d7..ee1d180 100644
--- a/plugins-root/pst3.c
+++ b/plugins-root/pst3.c
@@ -1,16 +1,36 @@
1/* pst3.c 1/*****************************************************************************
2*
3* pst3
4*
5* License: GPL
6* Copyright (c) 2008 Nagios Plugin Development Team
7*
8* Description:
9*
10* This file contains the pst3 executable. This is a replacement ps command
11* for Solaris to get output which provides a long argument listing, which
12* is not possible with the standard ps command (due to truncation). /usr/ucb/ps
13* also has issues where some fields run into each other.
14*
15* This executable works by reading the kernel memory structures, so needs
16* to be executed as root
2* 17*
3* Third version to get process arg info; this time by using 18* Originally written by R.W.Ingraham
4* a combination of reading the /proc/<pid>/psinfo structures 19*
5* and reading the complete arg vector from kernel memory structures. 20* This program is free software: you can redistribute it and/or modify
6* 21* it under the terms of the GNU General Public License as published by
7* Developed and tested under Solaris 5.8 (both 32 and 64 bit modes). 22* the Free Software Foundation, either version 3 of the License, or
8* 23* (at your option) any later version.
9* NOTE: This program must be setuid-root (or run by root) to work! 24*
10* 25* This program is distributed in the hope that it will be useful,
11* Written: 2005-04-28 R.W.Ingraham 26* but WITHOUT ANY WARRANTY; without even the implied warranty of
12*/ 27* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 28* GNU General Public License for more details.
29*
30* You should have received a copy of the GNU General Public License
31* along with this program. If not, see <http://www.gnu.org/licenses/>.
32*
33*****************************************************************************/
14 34
15#define _KMEMUSER 1 35#define _KMEMUSER 1
16 36
@@ -37,6 +57,8 @@
37 57
38#define PROC_DIR "/proc" 58#define PROC_DIR "/proc"
39#define MAX_PATH 1024 59#define MAX_PATH 1024
60#define OK 0
61#define FAIL NULL
40 62
41 63
42/* 64/*
@@ -59,12 +81,9 @@ static char ** myArgv;
59 * Prototypes 81 * Prototypes
60 */ 82 */
61 83
62static int HandleFile (struct dirent *pDent); 84static int output_info(struct proc *proc_kvm, psinfo_t procinfo,char **proc_argv);
63static int HandlePsInfo (char *szPath, psinfo_t *pPsInfo); 85static psinfo_t get_procinfo(struct proc *proc);
64static int GetArgVectors (pid_t pid); 86static int HandleProc(struct proc *proc);
65static void ShowArgVectors (void);
66static void ReleaseArgVectors();
67
68 87
69/*----------------------------------------------------------------------------*/ 88/*----------------------------------------------------------------------------*/
70 89
@@ -73,7 +92,8 @@ int main (int argc, char **argv)
73 DIR *pDir; 92 DIR *pDir;
74 struct dirent *pDent; 93 struct dirent *pDent;
75 int retcode = 0; 94 int retcode = 0;
76 95 struct proc *proc;
96 struct pid pid;
77 97
78 /* Set our program name global */ 98 /* Set our program name global */
79 if ((szProg = strrchr(argv[0], '/')) != NULL) 99 if ((szProg = strrchr(argv[0], '/')) != NULL)
@@ -95,26 +115,28 @@ int main (int argc, char **argv)
95 exit(2); 115 exit(2);
96 } 116 }
97 117
98 /* Open the /proc directory */ 118 /* reset to first proc in list */
99 if ((pDir = opendir(PROC_DIR)) != NULL) 119 if(kvm_setproc(kd) == -1) {
100 { 120 perror("kvm_setproc");
101 /* Display column headings */ 121 exit(2);
102 printf("S UID PID PPID VSZ RSS %%CPU COMMAND ARGS\n"); 122 }
103 123
104 /* Zip through all of the process entries */ 124 /* Display column headings */
105 while ((pDent = readdir(pDir)) != NULL) 125 printf("%c %5s %5s %5s %6s %6s %4s %s %s\n",
106 { 126 'S',
107 /* Handle each pid sub-directory */ 127 "UID",
108 HandleFile(pDent); 128 "PID",
109 } 129 "PPID",
110 130 "VSZ",
111 /* Close the directory */ 131 "RSS",
112 closedir(pDir); 132 "%CPU",
113 } 133 "COMMAND",
114 else /* ERROR: Failure to open PROC_DIR */ 134 "ARGS"
115 { 135 );
116 fprintf(stderr, "%s: Failed to open \"%s\": %s\n", szProg, PROC_DIR, strerror(errno)); 136
117 retcode = 3; 137 /* Zip through all of the process entries */
138 while((proc = kvm_nextproc(kd)) != 0) {
139 HandleProc(proc);
118 } 140 }
119 141
120 /* Close the handle to the running kernel image */ 142 /* Close the handle to the running kernel image */
@@ -125,129 +147,76 @@ int main (int argc, char **argv)
125 147
126/*----------------------------------------------------------------------------*/ 148/*----------------------------------------------------------------------------*/
127 149
128static int HandleFile (struct dirent *pDent) 150static int HandleProc(struct proc *proc)
129{ 151{
130 char szPath[MAX_PATH]; 152 struct pid pid;
131 psinfo_t sPsInfo; 153 struct user *user;
132 int fd, len; 154 psinfo_t procinfo;
133 int rc = 0; 155 char **proc_argv = 0;
134
135 /* Skip files beginning with a "." */
136 if (pDent->d_name[0] == '.')
137 return 0;
138
139 /* Cosntruct the path to the psinfo file */
140 len = sprintf(szPath, "%s/%s/psinfo", PROC_DIR, pDent->d_name);
141
142 /* Open the psinfo file for this pid and print out its arg vectors */
143 if ((fd = open(szPath, O_RDONLY)) >= 0)
144 {
145 /* Read the psinfo struct */
146 if ((len = read(fd, &sPsInfo, sizeof(sPsInfo))) != sizeof(sPsInfo))
147 {
148 rc = errno;
149 fprintf(stderr, "%s: Read error of psinfo structure (%d)\n", szPath, len);
150 return rc;
151 }
152
153 /* Close the psinfo file */
154 close(fd);
155 156
156 /* Pass psinfo struct to reporting function */ 157 if(kvm_kread(kd, (unsigned long) proc->p_pidp, (char *) &pid, sizeof pid) == -1) {
157 HandlePsInfo(szPath, &sPsInfo); 158 perror("kvm_read error");
158 } 159 exit(2);
159 else if (errno != ENOENT)
160 {
161 rc = errno;
162 fprintf(stderr, "%s: %s\n", szPath, strerror(errno));
163 } 160 }
161 proc->p_pidp = &pid;
162 user = kvm_getu(kd, proc);
164 163
165 return 0; 164 if(kvm_getcmd(kd, proc, user, &proc_argv, NULL) == -1) {
166} 165 return FAIL;
167
168/*----------------------------------------------------------------------------*/
169
170static int HandlePsInfo (char *szPath, psinfo_t *pPsInfo)
171{
172 int retcode;
173 char *thisProg;
174
175 /* Make sure that the process is still there */
176 if ((retcode = GetArgVectors(pPsInfo->pr_pid)) == 0)
177 {
178 /* We use the program name from the kvm argv[0] instead
179 * of pr_fname from the psinfo struct because pr_fname
180 * may be truncated.
181 *
182 * Also, strip-off leading path information.
183 */
184 if ((thisProg = strrchr(myArgv[0], '/')) != NULL)
185 thisProg++;
186 else
187 thisProg = myArgv[0];
188
189 /* Display the ps columns (except for argv) */
190 printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ",
191 pPsInfo->pr_lwp.pr_sname,
192 (int)(pPsInfo->pr_euid),
193 (int)(pPsInfo->pr_pid),
194 (int)(pPsInfo->pr_ppid),
195 (unsigned long)(pPsInfo->pr_size),
196 (unsigned long)(pPsInfo->pr_rssize),
197 ((float)(pPsInfo->pr_pctcpu) / 0x8000 * 100.0),
198 thisProg);
199
200 /* Display the arg vectors associated with this pid */
201 ShowArgVectors();
202
203 /* Release the arg vector buffer memory */
204 ReleaseArgVectors();
205 } 166 }
206 167
207 return retcode; 168 procinfo = get_procinfo(proc);
169 return output_info(proc, procinfo, proc_argv);
208} 170}
209 171
210/*----------------------------------------------------------------------------*/ 172static psinfo_t get_procinfo(struct proc *proc)
211
212static int GetArgVectors (pid_t pid)
213{ 173{
214 int retcode = 1; 174 char procpath[MAX_PATH];
175 psinfo_t procinfo;
176 int fd, len;
177
178 sprintf(procpath, "/proc/%d/psinfo", proc->p_pidp->pid_id);
215 179
216 /* Get the proc structure for the specified PID */ 180 if ((fd = open(procpath, O_RDONLY)) >= 0)
217 if ((pProc = kvm_getproc(kd, pid)) != NULL)
218 { 181 {
219 /* Save a copy of the process' u-area */ 182 if ((len = read(fd, &procinfo, sizeof(procinfo))) != sizeof(procinfo))
220 if ((pUser = kvm_getu(kd, pProc)) != NULL)
221 { 183 {
222 /* Reconstruct the process' argv vector array */ 184 fprintf(stderr,"%s: Read error of psingo structure (%d)\n", procpath, len);
223 if (kvm_getcmd(kd, pProc, pUser, &myArgv, NULL) == 0) 185 exit(2);
224 {
225 retcode = 0;
226 }
227 } 186 }
187 close(fd);
228 } 188 }
189 return procinfo;
229 190
230 return retcode;
231} 191}
232 192
233/*----------------------------------------------------------------------------*/ 193static int output_info(struct proc *proc_kvm, psinfo_t procinfo, char **proc_argv)
234
235static void ShowArgVectors (void)
236{ 194{
195 char *procname;
237 int i; 196 int i;
238 197
239 for (i=0; myArgv[i]; i++) 198 if((procname = strrchr(proc_argv[0], '/')) != NULL)
240 { 199 procname++;
241 printf(" %s", myArgv[i]); 200 else
201 procname = proc_argv[0];
202
203 printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ",
204 procinfo.pr_lwp.pr_sname,
205 (int)(procinfo.pr_euid),
206 (int)proc_kvm->p_pidp->pid_id,
207 (int)proc_kvm->p_ppid,
208 (unsigned long)(procinfo.pr_size),
209 (unsigned long)(procinfo.pr_rssize),
210 ((float)(procinfo.pr_pctcpu) / 0x8000 * 100.0),
211 procname
212 );
213
214 for(i=0;proc_argv[i];i++) {
215 printf(" %s", proc_argv[i]);
242 } 216 }
243 printf("\n");
244}
245 217
246/*----------------------------------------------------------------------------*/ 218 printf("\n");
247 219
248static void ReleaseArgVectors() 220 return OK;
249{
250 /* NOOP */
251} 221}
252 222
253/*----------------------------------------------------------------------------*/