Skip to content

Commit 4ec880f

Browse files
author
Webslice
committed
Add incron_plugin, fixes #5218
1 parent 061583c commit 4ec880f

File tree

1 file changed

+162
-0
lines changed

1 file changed

+162
-0
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
<?php
2+
3+
/**
4+
* If your websites use PHP-FPM and you have incron installed, you can use this plugin to automatically add incron
5+
* configuration which will take care of reloading the php-fpm pool when the file /private/php-fpm.reload is touched.
6+
* Projects which use deployment tools can use this to reload php-fpm to clear the opcache at deploy time, without
7+
* requiring superuser privileges.
8+
*/
9+
class incron_plugin {
10+
11+
var $plugin_name = 'incron_plugin';
12+
var $class_name = 'incron_plugin';
13+
14+
function onInstall() {
15+
global $conf;
16+
17+
if ($conf['services']['web'] !== true) {
18+
return false;
19+
}
20+
21+
if ($this->isIncronAvailable() === false) {
22+
return false;
23+
}
24+
25+
return true;
26+
}
27+
28+
function onLoad() {
29+
global $app;
30+
31+
$app->plugins->registerEvent('web_domain_insert', $this->plugin_name, 'incronInsert');
32+
$app->plugins->registerEvent('web_domain_update', $this->plugin_name, 'incronUpdate');
33+
$app->plugins->registerEvent('web_domain_delete', $this->plugin_name, 'incronDelete');
34+
}
35+
36+
function incronInsert($eventName, $data) {
37+
$this->setup($data['new']);
38+
}
39+
40+
function incronUpdate($eventName, $data) {
41+
global $app;
42+
43+
if ($data['new']['document_root'] === $data['old']['document_root']) {
44+
$app->log('Document root unchanged. Not updating incron configuration.', LOGLEVEL_DEBUG);
45+
46+
return;
47+
}
48+
49+
$this->teardown($data['old']);
50+
$this->setup($data['new']);
51+
}
52+
53+
function incronDelete($eventName, $data) {
54+
$this->teardown($data['old']);
55+
}
56+
57+
private function setup($data)
58+
{
59+
$triggerFile = $this->getTriggerFilePath($data['document_root']);
60+
61+
$this->createTriggerFile($triggerFile, $data['system_user'], $data['system_group']);
62+
$this->createIncronConfiguration(
63+
$triggerFile,
64+
$data['system_user'],
65+
$data['fastcgi_php_version']
66+
);
67+
68+
$this->restartIncronService();
69+
}
70+
71+
private function teardown($data) {
72+
$this->deleteIncronConfiguration($data['system_user']);
73+
$this->deleteTriggerFile($this->getTriggerFilePath($data['document_root']));
74+
75+
$file = sprintf('/etc/incron.d/%s.conf', $data['system_user']);
76+
77+
@unlink($file);
78+
79+
$this->restartIncronService();
80+
}
81+
82+
private function isIncronAvailable() {
83+
exec('which incrond', $output, $retval);
84+
85+
return $retval === 0;
86+
}
87+
88+
private function createIncronConfiguration($triggerFile, $systemUser, $fastcgiPhpVersion) {
89+
global $app;
90+
91+
$phpService = $this->getPhpService($fastcgiPhpVersion);
92+
$configFile = $this->getIncronConfigurationFilePath($systemUser);
93+
94+
$content = sprintf(
95+
'%s %s %s',
96+
$triggerFile,
97+
'IN_CLOSE_WRITE',
98+
$app->system->getinitcommand($phpService, 'reload')
99+
);
100+
101+
file_put_contents($configFile, $content);
102+
103+
$app->log(sprintf('Created incron configuration "%s"', $configFile), LOGLEVEL_DEBUG);
104+
}
105+
106+
private function createTriggerFile($triggerFile, $systemUser, $systemGroup) {
107+
global $app;
108+
109+
if (!file_exists($triggerFile)) {
110+
exec(sprintf('touch %s', $triggerFile));
111+
}
112+
113+
exec(sprintf('chown %s:%s %s', $systemUser, $systemGroup, $triggerFile));
114+
115+
$app->log(sprintf('Ensured incron trigger file "%s"', $triggerFile), LOGLEVEL_DEBUG);
116+
}
117+
118+
private function deleteIncronConfiguration($systemUser) {
119+
global $app;
120+
121+
$configFile = $this->getIncronConfigurationFilePath($systemUser);
122+
unlink($configFile);
123+
124+
$app->log(sprintf('Deleted incron configuration "%s"', $configFile), LOGLEVEL_DEBUG);
125+
}
126+
127+
private function deleteTriggerFile($triggerFile) {
128+
global $app;
129+
130+
unlink($triggerFile);
131+
132+
$app->log(sprintf('Deleted incron trigger file "%s"', $triggerFile), LOGLEVEL_DEBUG);
133+
}
134+
135+
private function getTriggerFilePath($documentRoot) {
136+
return sprintf('%s/private/php-fpm.reload', $documentRoot);
137+
}
138+
139+
private function getIncronConfigurationFilePath($systemUser) {
140+
return sprintf('/etc/incron.d/%s.conf', $systemUser);
141+
}
142+
143+
private function getPhpService($fastcgiPhpVersion) {
144+
$phpInfo = explode(':', $fastcgiPhpVersion);
145+
if (empty($phpInfo)) {
146+
return null;
147+
}
148+
149+
$phpService = $phpInfo[1];
150+
if (empty($phpService)) {
151+
return null;
152+
}
153+
154+
return $phpService;
155+
}
156+
157+
private function restartIncronService() {
158+
global $app;
159+
160+
exec($app->system->getinitcommand('incrond', 'restart'));
161+
}
162+
}

0 commit comments

Comments
 (0)