1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace CyberLine\SystemdState; |
4
|
|
|
|
5
|
|
|
class SystemdState |
6
|
|
|
{ |
7
|
|
|
private static $command = '/bin/systemctl show %s --no-page'; |
8
|
|
|
|
9
|
|
|
private $services = []; |
10
|
|
|
|
11
|
|
|
private $reports = []; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* SystemdState constructor. |
15
|
|
|
* @param array $services |
16
|
|
|
*/ |
17
|
|
|
public function __construct(array $services = []) |
18
|
|
|
{ |
19
|
|
|
foreach ($services as $service) { |
20
|
|
|
$this->addCheckUnit($service); |
21
|
|
|
} |
22
|
|
|
} |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @param string $name |
26
|
|
|
* @return SystemdState |
27
|
|
|
*/ |
28
|
|
|
public function addCheckUnit(string $name): self |
29
|
|
|
{ |
30
|
|
|
$this->services[] = escapeshellcmd($name); |
31
|
|
|
|
32
|
|
|
return $this; |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
public function addAllUnits(): self |
36
|
|
|
{ |
37
|
|
|
$this->addCheckUnit('*'); |
38
|
|
|
|
39
|
|
|
return $this; |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @return array |
44
|
|
|
*/ |
45
|
|
|
public function getSystemdInfo() |
46
|
|
|
{ |
47
|
|
|
$this->addCheckUnit(''); |
48
|
|
|
|
49
|
|
|
return $this->getReport('systemd'); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @param null $unitName |
54
|
|
|
* @return array |
55
|
|
|
*/ |
56
|
|
|
public function getReport($unitName = null): array |
57
|
|
|
{ |
58
|
|
|
if (!$this->reports) { |
|
|
|
|
59
|
|
|
$this->checkState(); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
if (!$unitName) { |
63
|
|
|
return $this->reports; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
if (array_key_exists($unitName, $this->reports)) { |
67
|
|
|
return [$this->reports[$unitName]]; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
$retval = []; |
71
|
|
|
foreach ([ |
72
|
|
|
'service', |
73
|
|
|
'target', |
74
|
|
|
'timer', |
75
|
|
|
'slice', |
76
|
|
|
'socket', |
77
|
|
|
'path', |
78
|
|
|
'device', |
79
|
|
|
'mount', |
80
|
|
|
'automount', |
81
|
|
|
'scope', |
82
|
|
|
'swap', |
83
|
|
|
] as $suffix) { |
84
|
|
|
$tempName = $unitName . '.' . $suffix; |
85
|
|
|
if (array_key_exists($tempName, $this->reports)) { |
86
|
|
|
$retval[$tempName] = $this->reports[$tempName]; |
87
|
|
|
} |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
if (count($retval)) { |
91
|
|
|
return $retval; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
throw new \RangeException(sprintf('No report found for `%s`. Maybe misspelled?', $unitName)); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
private function checkState() |
98
|
|
|
{ |
99
|
|
|
if (!count($this->services)) { |
100
|
|
|
throw new \InvalidArgumentException('You have to add at least one unit to check!'); |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
$command = sprintf(self::$command, implode(' ', $this->services)); |
104
|
|
|
$exec = shell_exec($command); |
105
|
|
|
|
106
|
|
|
if ($exec === null) { |
107
|
|
|
throw new \RuntimeException(sprintf('There was an error executing the command: `%s`', $command)); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
$services = explode(PHP_EOL . PHP_EOL, $exec); |
111
|
|
|
|
112
|
|
|
foreach ($services as $service) { |
113
|
|
|
$this->handleServiceResponse($service); |
114
|
|
|
} |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* @param string $service |
119
|
|
|
*/ |
120
|
|
|
private function handleServiceResponse(string $service) |
121
|
|
|
{ |
122
|
|
|
$split = explode(PHP_EOL, $service); |
123
|
|
|
|
124
|
|
|
preg_match('/Id=(?<name>.*)/m', $service, $matches); |
125
|
|
|
if (!$matches) { |
|
|
|
|
126
|
|
|
$type = 'Systemd'; |
127
|
|
|
} else { |
128
|
|
|
$explode = explode('.', $matches['name']); |
129
|
|
|
$type = ucfirst($explode[count($explode) - 1]); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
$class = 'CyberLine\SystemdState\Types\\' . $type; |
133
|
|
|
$class = new $class(); |
134
|
|
|
|
135
|
|
|
foreach ($split as $line) { |
136
|
|
|
$explode = explode('=', $line); |
137
|
|
|
if (empty($explode[0])) { |
138
|
|
|
continue; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
$class->{'set' . $explode[0]}(Parser::parseValueByContent($explode)); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
$this->reports[$class->getId()] = $class; |
145
|
|
|
} |
146
|
|
|
} |
147
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.