Subversion Repositories ALCASAR

Rev

Go to most recent revision | Details | Last modification | View Log

Rev Author Line No. Line
2782 rexy 1
<?php
2
/**
3
 * PS Plugin, which displays all running processes
4
 * a simple tree view which is filled with the running processes which are determined by
5
 * calling the "ps" command line utility, another way is to provide
6
 * a file with the output of the ps utility, so there is no need to run a execute by the
7
 * webserver, the format of the command is written down in the phpsysinfo.ini file, where also
8
 * the method of getting the information is configured
9
 *
10
 * @category  PHP
11
 * @package   PSI_Plugin_PS
12
 * @author    Michael Cramer <BigMichi1@users.sourceforge.net>
13
 * @copyright 2009 phpSysInfo
14
 * @license   http://opensource.org/licenses/gpl-2.0.php GNU General Public License version 2, or (at your option) any later version
15
 * @version   Release: 3.0
16
 * @link      http://phpsysinfo.sourceforge.net
17
 */
18
class PS extends PSI_Plugin
19
{
20
    /**
21
     * variable, which holds the content of the command
22
     * @var array
23
     */
24
    private $_filecontent = array();
25
    /**
26
     * variable, which holds the result before the xml is generated out of this array
27
     * @var array
28
     */
29
    private $_result = array();
30
    /**
31
     * read the data into an internal array and also call the parent constructor
32
     *
33
     * @param string $enc encoding
34
     */
35
    public function __construct($enc)
36
    {
37
        parent::__construct(__CLASS__, $enc);
38
        switch (strtolower(PSI_PLUGIN_PS_ACCESS)) {
39
        case 'command':
40
            if (PSI_OS == 'WINNT') {
41
                try {
42
                    $objLocator = new COM('WbemScripting.SWbemLocator');
43
                    $wmi = $objLocator->ConnectServer('', 'root\CIMv2');
44
                    $os_wmi = CommonFunctions::getWMI($wmi, 'Win32_OperatingSystem', array('TotalVisibleMemorySize'));
45
                    $memtotal = 0;
46
                    foreach ($os_wmi as $os) {
47
                        $memtotal = $os['TotalVisibleMemorySize'] * 1024;
48
                        break;
49
                    }
50
 
51
                    $perf_wmi = CommonFunctions::getWMI($wmi, 'Win32_PerfFormattedData_PerfProc_Process', array('IDProcess', 'CreatingProcessID', 'PercentProcessorTime'));
52
                    $proccpu = array();
53
                    foreach ($perf_wmi as $perf) {
54
                        $proccpu[trim($perf['IDProcess'])] = array('ParentProcessId'=>trim($perf['CreatingProcessID']), 'PercentProcessorTime'=>trim($perf['PercentProcessorTime']));
55
                    }
56
 
57
                    $process_wmi = CommonFunctions::getWMI($wmi, 'Win32_Process', array('Caption', 'CommandLine', 'ProcessId', 'ParentProcessId', 'WorkingSetSize'));
58
                    foreach ($process_wmi as $process) {
59
                        if (strlen(trim($process['CommandLine'])) > 0) {
60
                            $ps = trim($process['CommandLine']);
61
                        } else {
62
                            $ps = trim($process['Caption']);
63
                        }
64
                        if (($procid = trim($process['ProcessId'])) != 0) {
65
                            $memusage = round(trim($process['WorkingSetSize']) * 100 / $memtotal, 1);
66
                            $parentid  = trim($process['ParentProcessId']);
67
                            $cpu = 0;
68
                            if (isset($proccpu[$procid]) && ($proccpu[$procid]['ParentProcessId'] == $parentid)) {
69
                                $cpu = $proccpu[$procid]['PercentProcessorTime'];
70
                            }
71
                            //ParentProcessId
72
                            //Unique identifier of the process that creates a process. Process identifier numbers are reused, so they
73
                            //only identify a process for the lifetime of that process. It is possible that the process identified by
74
                            //ParentProcessId is terminated, so ParentProcessId may not refer to a running process. It is also
75
                            //possible that ParentProcessId incorrectly refers to a process that reuses a process identifier. You can
76
                            //use the CreationDate property to determine whether the specified parent was created after the process
77
                            //represented by this Win32_Process instance was created.
78
                            //=> subtrees of processes may be missing (WHAT TODO?!?)
79
                            $this->_filecontent[] = $procid." ".$parentid." ".$memusage." ".$cpu." ".$ps;
80
                        }
81
                    }
82
                } catch (Exception $e) {
83
                }
84
            } else {
85
                CommonFunctions::executeProgram("ps", "axo pid,ppid,pmem,pcpu,args", $buffer, PSI_DEBUG);
86
                if (((PSI_OS == 'Linux') || (PSI_OS == 'Android')) && (!preg_match("/^[^\n]+\n\s*\d+\s+\d+\s+[\d\.]+\s+[\d\.]+\s+.+/", $buffer))) { //alternative method if no data
87
                    if (CommonFunctions::rfts('/proc/meminfo', $mbuf)) {
88
                        $bufe = preg_split("/\n/", $mbuf, -1, PREG_SPLIT_NO_EMPTY);
89
                        $totalmem = 0;
90
                        foreach ($bufe as $buf) {
91
                            if (preg_match('/^MemTotal:\s+(\d+)\s*kB/i', $buf, $ar_buf)) {
92
                                $totalmem = $ar_buf[1];
93
                                break;
94
                            }
95
                        }
96
                        $buffer = "  PID  PPID %MEM %CPU COMMAND\n";
97
 
98
                        $processlist = glob('/proc/*/status', GLOB_NOSORT);
99
                        if (is_array($processlist) && (($total = count($processlist)) > 0)) {
100
                            natsort($processlist); //first sort
101
                            $process = array();
102
                            foreach ($processlist as $processitem) { //second sort
103
                                $process[] = $processitem;
104
                            }
105
 
106
                            $buf = "";
107
                            for ($i = 0; $i < $total; $i++) {
108
                                if (CommonFunctions::rfts($process[$i], $buf, 0, 4096, false)) {
109
 
110
                                    if (($totalmem != 0) && (preg_match('/^VmRSS:\s+(\d+)\s+kB/m', $buf, $tmppmem))) {
111
                                        $pmem = round(100 * $tmppmem[1] / $totalmem, 1);
112
                                    } else {
113
                                        $pmem = 0;
114
                                    }
115
 
116
                                    $name = null;
117
                                    if (CommonFunctions::rfts(substr($process[$i], 0, strlen($process[$i])-6)."cmdline", $namebuf, 0, 4096, false)) {
118
                                        $name = str_replace(chr(0), ' ', trim($namebuf));
119
                                    }
120
                                    if (preg_match('/^Pid:\s+(\d+)/m', $buf, $tmppid) &&
121
                                        preg_match('/^PPid:\s+(\d+)/m', $buf, $tmpppid) &&
122
                                        preg_match('/^Name:\s+(.+)/m', $buf, $tmpargs)) {
123
                                        $pid = $tmppid[1];
124
                                        $ppid = $tmpppid[1];
125
                                        $args = $tmpargs[1];
126
                                        if ($name !== null) {
127
                                            if ($name !== "") {
128
                                                $args = $name;
129
                                            } else {
130
                                                $args = "[".$args."]";
131
                                            }
132
                                        }
133
                                        $buffer .= $pid." ".$ppid." ".$pmem." 0.0 ".$args."\n";
134
                                    }
135
 
136
                                }
137
                            }
138
                        }
139
                    }
140
                }
141
            }
142
            break;
143
        case 'data':
144
            CommonFunctions::rfts(PSI_APP_ROOT."/data/ps.txt", $buffer);
145
            break;
146
        default:
147
            $this->global_error->addConfigError("__construct()", "[ps] ACCESS");
148
            break;
149
        }
150
        if (PSI_OS != 'WINNT') {
151
            if (trim($buffer) != "") {
152
                $this->_filecontent = preg_split("/\n/", $buffer, -1, PREG_SPLIT_NO_EMPTY);
153
                unset($this->_filecontent[0]);
154
            } else {
155
                $this->_filecontent = array();
156
            }
157
        }
158
    }
159
    /**
160
     * doing all tasks to get the required informations that the plugin needs
161
     * result is stored in an internal array<br>the array is build like a tree,
162
     * so that it is possible to get only a specific process with the childs
163
     *
164
     * @return void
165
     */
166
    public function execute()
167
    {
168
        if (empty($this->_filecontent)) {
169
            return;
170
        }
171
        $items = array();
172
        foreach ($this->_filecontent as $roworig) {
173
            $row = preg_split("/[\s]+/", trim($roworig), 5);
174
            if (count($row) != 5) {
175
                break;
176
            }
177
            foreach ($row as $key=>$val) {
178
                $items[$row[0]][$key] = $val;
179
            }
180
            if ($row[1] !== $row[0]) {
181
                $items[$row[1]]['childs'][$row[0]] = &$items[$row[0]];
182
            }
183
        }
184
        foreach ($items as $item) { //find zombie
185
            if (!isset($item[0])) {
186
                foreach ($item["childs"] as $subitem) {
187
                    $zombie = $subitem[1];
188
                    if ($zombie != 0) {
189
                        $items[$zombie]["0"] = $zombie;
190
                        $items[$zombie]["1"] = "0";
191
                        $items[$zombie]["2"] = "0";
192
                        $items[$zombie]["3"] = "0";
193
                        $items[$zombie]["4"] = "unknown";
194
                        $items[0]['childs'][$zombie] = &$items[$zombie];
195
                    }
196
                    break; //first is sufficient
197
                }
198
            }
199
        }
200
        if (isset($items[0])) {
201
            $this->_result = $items[0];
202
        } else {
203
            $this->_result = array();
204
        }
205
    }
206
    /**
207
     * generates the XML content for the plugin
208
     *
209
     * @return SimpleXMLElement entire XML content for the plugin
210
     */
211
    public function xml()
212
    {
213
        if ($this->_result) {
214
            $positions = array(0=>0);
215
            $this->_addchild($this->_result['childs'], $this->xml, $positions);
216
        }
217
 
218
        return $this->xml->getSimpleXmlElement();
219
    }
220
    /**
221
     * recursive function to allow appending child processes to a parent process
222
     *
223
     * @param array             $child      part of the array which should be appended to the XML
224
     * @param SimpleXMLExtended $xml        XML-Object to which the array content is appended
225
     * @param array             &$positions array with parent positions in xml structure
226
     *
227
     * @return SimpleXMLExtended Object with the appended array content
228
     */
229
    private function _addchild($child, SimpleXMLExtended $xml, &$positions)
230
    {
231
        foreach ($child as $key=>$value) {
232
            $xmlnode = $xml->addChild("Process");
233
            if (isset($value[0])) {
234
                array_push($positions, $value[0]);
235
                $xmlnode->addAttribute('PID', $value[0]);
236
                $parentid = array_search($value[1], $positions);
237
                $xmlnode->addAttribute('ParentID', $parentid);
238
                $xmlnode->addAttribute('PPID', $value[1]);
239
                if (!defined('PSI_PLUGIN_PS_MEMORY_USAGE') || (PSI_PLUGIN_PS_MEMORY_USAGE !== false)) {
240
                    $xmlnode->addAttribute('MemoryUsage', $value[2]);
241
                }
242
                if (!defined('PSI_PLUGIN_PS_CPU_USAGE') || (PSI_PLUGIN_PS_CPU_USAGE !== false)) {
243
                    $xmlnode->addAttribute('CPUUsage', $value[3]);
244
                }
245
                $xmlnode->addAttribute('Name', $value[4]);
246
                if ((PSI_OS !== 'WINNT') &&
247
                    ((($parentid === 1) && (!defined('PSI_PLUGIN_PS_SHOW_PID1CHILD_EXPANDED') || (PSI_PLUGIN_PS_SHOW_PID1CHILD_EXPANDED === false)))
248
                    || ((!defined('PSI_PLUGIN_PS_SHOW_KTHREADD_EXPANDED') || (PSI_PLUGIN_PS_SHOW_KTHREADD_EXPANDED === false)) && ($value[4] === "[kthreadd]")))) {
249
                    $xmlnode->addAttribute('Expanded', 0);
250
                }
251
            }
252
            if (isset($value['childs'])) {
253
                $this->_addChild($value['childs'], $xml, $positions);
254
            }
255
        }
256
 
257
        return $xml;
258
    }
259
}